diff --git a/docbow_project/docbow/actions.py b/docbow_project/docbow/actions.py
index 585f41c..694665c 100644
--- a/docbow_project/docbow/actions.py
+++ b/docbow_project/docbow/actions.py
@@ -18,22 +18,30 @@ def export_as_csv(modeladmin, request, queryset):
field_names = [field.name for field in opts.fields]
m2m_field_names = [m2m_field.name for m2m_field in opts.many_to_many]
# Write a first row with header information
- writer.writerow(field_names+m2m_field_names)
+ writer.writerow(field_names + m2m_field_names)
# Write data rows
for obj in queryset:
- values = [ force_text(getattr(obj, field)) for field in field_names]
+ values = [force_text(getattr(obj, field)) for field in field_names]
for m2m_field in m2m_field_names:
value = getattr(obj, m2m_field)
value = u','.join(map(force_text, value.all()))
values.append(force_text(value))
writer.writerow(map(lambda x: force_str(x), values))
return response
+
+
export_as_csv.short_description = _("Export selected objects as csv file")
+
def activate_selected(modeladmin, request, queryset):
queryset.update(is_active=True)
+
+
activate_selected.short_description = _('Activate selected objects')
+
def deactivate_selected(modeladmin, request, queryset):
queryset.update(is_active=False)
+
+
deactivate_selected.short_description = _('De-activate selected objects')
diff --git a/docbow_project/docbow/admin.py b/docbow_project/docbow/admin.py
index e306d82..d631d2c 100644
--- a/docbow_project/docbow/admin.py
+++ b/docbow_project/docbow/admin.py
@@ -8,6 +8,7 @@ from django.core.exceptions import PermissionDenied
from django.urls import reverse, NoReverseMatch
from django.conf.urls import url
from django.utils.safestring import mark_safe
+
try:
import thread
except ImportError:
@@ -33,39 +34,41 @@ class DocbowAdminSite(admin.AdminSite):
site = DocbowAdminSite('docbow_admin')
site.disable_action('delete_selected')
+
class DocumentAdmin(admin.ModelAdmin):
- list_display = [ 'date', 'sender', 'recipients', 'filetype', 'filename_links', 'comment', 'private' ]
- list_filter = [ 'sender', 'to_user', 'to_list', 'filetype', 'private']
- fields = [ 'date', 'sender', 'recipients', 'filetype', 'filename_links', 'comment', 'private' ]
+ list_display = ['date', 'sender', 'recipients', 'filetype', 'filename_links', 'comment', 'private']
+ list_filter = ['sender', 'to_user', 'to_list', 'filetype', 'private']
+ fields = ['date', 'sender', 'recipients', 'filetype', 'filename_links', 'comment', 'private']
readonly_fields = fields
- filter_horizontal = [ 'to_user', 'to_list']
+ filter_horizontal = ['to_user', 'to_list']
date_hierarchy = 'date'
class SendingLimitationAdmin(admin.ModelAdmin):
- list_display = [ 'mailing_list', 'filetypes_list', 'lists_list' ]
- filter_horizontal = [ 'filetypes', 'lists' ]
- actions = [ actions.export_as_csv, 'delete_selected' ]
+ list_display = ['mailing_list', 'filetypes_list', 'lists_list']
+ filter_horizontal = ['filetypes', 'lists']
+ actions = [actions.export_as_csv, 'delete_selected']
def lists_list(self, obj):
'''Display method for the field lists'''
return ', '.join(obj.lists.values_list('name', flat=True))
+
lists_list.short_description = _('Limitation des destinataires')
def filetypes_list(self, obj):
'''Display method for the field filetypes'''
return ', '.join(obj.filetypes.values_list('name', flat=True))
+
filetypes_list.short_description = _('Limitation des types de fichier')
class MailingListAdmin(admin.ModelAdmin):
- list_display = [ 'name', 'is_active' ]
- list_filter = [ 'is_active' ]
- search_fields = [ 'name', 'members__username', 'members__first_name',
- 'members__last_name' ]
+ list_display = ['name', 'is_active']
+ list_filter = ['is_active']
+ search_fields = ['name', 'members__username', 'members__first_name', 'members__last_name']
ordering = ['name']
form = forms.MailingListForm
- actions = [ actions.export_as_csv ]
+ actions = [actions.export_as_csv]
def get_actions(self, request):
'''Show delete actions only if user has delete rights
@@ -86,9 +89,7 @@ class AttachedFileAdmin(admin.ModelAdmin):
def get_urls(self):
urls = super(AttachedFileAdmin, self).get_urls()
- attached_file_urls = [
- url(r'^(.+)/download/$', self.download)
- ]
+ attached_file_urls = [url(r'^(.+)/download/$', self.download)]
return attached_file_urls + urls
def download(self, request, object_id):
@@ -110,12 +111,17 @@ class DocbowUserAdmin(auth_admin.UserAdmin):
(_('Important dates'), {'fields': ('last_login', 'date_joined')}),
(_('Groups'), {'fields': ('groups',)}),
)
- readonly_fields = [ 'last_login', 'date_joined' ]
- exclude = [ 'user_permissions' ]
- actions = [ actions.export_as_csv ]
- list_display = auth_admin.UserAdmin.list_display + ( 'guest_account',
- 'delegations', 'get_groups', 'get_lists', 'is_active')
- inlines = [ DocbowProfileInlineAdmin ]
+ readonly_fields = ['last_login', 'date_joined']
+ exclude = ['user_permissions']
+ actions = [actions.export_as_csv]
+ list_display = auth_admin.UserAdmin.list_display + (
+ 'guest_account',
+ 'delegations',
+ 'get_groups',
+ 'get_lists',
+ 'is_active',
+ )
+ inlines = [DocbowProfileInlineAdmin]
if 'mellon' in settings.INSTALLED_APPS:
@@ -129,10 +135,12 @@ class DocbowUserAdmin(auth_admin.UserAdmin):
def get_groups(self, user):
return u', '.join(group.name for group in user.groups.all())
+
get_groups.short_description = _('groups')
def get_lists(self, user):
return u', '.join(_list.name for _list in user.mailing_lists.all())
+
get_lists.short_description = _('mailing lists')
def get_actions(self, request):
@@ -149,22 +157,24 @@ class DocbowUserAdmin(auth_admin.UserAdmin):
return instance.docbowprofile.is_guest
except models.DocbowProfile.DoesNotExist:
return False
+
guest_account.boolean = True
guest_account.short_description = _('Guest account')
def delegations(self, instance):
- from_users = auth_models.User.objects.filter(
- delegations_to__to=instance)
+ from_users = auth_models.User.objects.filter(delegations_to__to=instance)
return models.list_to_csv(from_users, models.username)
+
delegations.short_description = _('Delegations by')
+
class DocbowGroupAdmin(auth_admin.GroupAdmin):
- exclude = [ 'permissions' ]
+ exclude = ['permissions']
class MailboxAdmin(admin.ModelAdmin):
- list_display = [ 'owner', 'document', 'date' ]
- list_filter = [ 'owner', 'outbox' ]
+ list_display = ['owner', 'document', 'date']
+ list_filter = ['owner', 'outbox']
def lookup_allowed(self, *args, **kwargs):
'''Allow complex filters'''
@@ -172,9 +182,9 @@ class MailboxAdmin(admin.ModelAdmin):
class InboxAdmin(MailboxAdmin):
- list_display = [ 'date', 'owner', 'document' ]
- fields = [ 'date', 'owner', 'document' ]
- readonly_fields = [ 'date', 'owner', 'document' ]
+ list_display = ['date', 'owner', 'document']
+ fields = ['date', 'owner', 'document']
+ readonly_fields = ['date', 'owner', 'document']
def queryset(self, request):
'''Only show input mailboxes'''
@@ -184,7 +194,7 @@ class InboxAdmin(MailboxAdmin):
class OutboxAdmin(MailboxAdmin):
- list_display = [ 'date', 'owner', 'document' ]
+ list_display = ['date', 'owner', 'document']
fields = list_display
readonly_fields = list_display
@@ -197,14 +207,13 @@ class OutboxAdmin(MailboxAdmin):
class ContentAdmin(admin.ModelAdmin):
verbose_name = _('Predefined content description')
- actions = [ actions.export_as_csv, 'delete_selected' ]
+ actions = [actions.export_as_csv, 'delete_selected']
class AutomaticForwardingAdmin(admin.ModelAdmin):
- filter_horizontal = [ 'filetypes', 'originaly_to_user', 'forward_to_user',
- 'forward_to_list' ]
+ filter_horizontal = ['filetypes', 'originaly_to_user', 'forward_to_user', 'forward_to_list']
form = forms.AutomaticForwardingForm
- actions = [ actions.export_as_csv, 'delete_selected' ]
+ actions = [actions.export_as_csv, 'delete_selected']
def formfield_for_manytomany(self, db_field, request, **kwargs):
if db_field.name in ('originaly_to_user', 'forward_to_user'):
@@ -219,16 +228,20 @@ class FileTypeAttachedFileKindAdmin(admin.TabularInline):
class FileTypeAdmin(admin.ModelAdmin):
- list_display = [ 'name', 'is_active' ]
- actions = [ actions.export_as_csv ]
- inlines = [ FileTypeAttachedFileKindAdmin ]
+ list_display = ['name', 'is_active']
+ actions = [actions.export_as_csv]
+ inlines = [FileTypeAttachedFileKindAdmin]
class NotificationAdmin(admin.ModelAdmin):
- search_fields = ['user__username', 'user__first_name',
- 'user__last_name', 'user__docbowprofile__mobile_phone']
- list_display = [ 'create_dt', '_document', 'user', 'kind', 'done', 'failure' ]
- readonly_fields = [ 'ctx' ]
+ search_fields = [
+ 'user__username',
+ 'user__first_name',
+ 'user__last_name',
+ 'user__docbowprofile__mobile_phone',
+ ]
+ list_display = ['create_dt', '_document', 'user', 'kind', 'done', 'failure']
+ readonly_fields = ['ctx']
date_hierarchy = 'create_dt'
list_filter = ['user', 'kind', 'done']
actions = ['retry', 'delete_selected']
@@ -236,14 +249,14 @@ class NotificationAdmin(admin.ModelAdmin):
def retry(self, request, queryset):
queryset.update(done=False, failure=None)
thread.start_new_thread(notification.process_notifications, ())
- retry.short_description = _('Clear failure and done field, resubmitting '
- 'the notifications.')
+
+ retry.short_description = _('Clear failure and done field, resubmitting ' 'the notifications.')
def object_link(self, obj):
if obj is not None:
- url = u'{0}:{1}_{2}_change'.format(self.admin_site.name,
- obj.__class__._meta.app_label,
- obj.__class__._meta.model_name)
+ url = u'{0}:{1}_{2}_change'.format(
+ self.admin_site.name, obj.__class__._meta.app_label, obj.__class__._meta.model_name
+ )
try:
url = reverse(url, args=(obj.id,))
return u'{1}'.format(url, obj)
@@ -253,6 +266,7 @@ class NotificationAdmin(admin.ModelAdmin):
def _document(self, notification):
return mark_safe(self.object_link(notification.document))
+
_document.short_description = _('Document')
@@ -262,21 +276,20 @@ class JournalAdmin(django_journal.admin.JournalAdmin):
user, delegate = '', ''
for objectdata in entry.objectdata_set.all():
if objectdata.tag.name == 'user':
- user = self.object_filter_link(objectdata) + \
- self.object_link(objectdata)
+ user = self.object_filter_link(objectdata) + self.object_link(objectdata)
if objectdata.tag.name == 'delegate':
- delegate = self.object_filter_link(objectdata) + \
- self.object_link(objectdata)
+ delegate = self.object_filter_link(objectdata) + self.object_link(objectdata)
if user and delegate:
return mark_safe(delegate + _(' as ') + user)
elif user:
return mark_safe(user)
return mark_safe(_('None'))
+
user.short_description = _('User')
class DelegationAdmin(admin.ModelAdmin):
- list_display = [ 'id', 'by', 'to' ]
+ list_display = ['id', 'by', 'to']
# Docbow Admin Site
diff --git a/docbow_project/docbow/app_settings.py b/docbow_project/docbow/app_settings.py
index 2615466..cb5d252 100644
--- a/docbow_project/docbow/app_settings.py
+++ b/docbow_project/docbow/app_settings.py
@@ -1,12 +1,12 @@
class AppSettings(object):
__DEFAULTS = {
- 'PERSONAL_EMAIL': True,
- 'MOBILE_PHONE': True,
- 'GROUP_LISTING': True,
- 'PRIVATE_DOCUMENTS': False,
- 'EDIT_EMAIL': False,
- 'DELEGATE_TO_EXISTING_USER': True,
- 'DEFAULT_ACCEPT_NOTIFICATIONS_FOR_GUEST': True,
+ 'PERSONAL_EMAIL': True,
+ 'MOBILE_PHONE': True,
+ 'GROUP_LISTING': True,
+ 'PRIVATE_DOCUMENTS': False,
+ 'EDIT_EMAIL': False,
+ 'DELEGATE_TO_EXISTING_USER': True,
+ 'DEFAULT_ACCEPT_NOTIFICATIONS_FOR_GUEST': True,
}
def __init__(self, prefix):
@@ -16,6 +16,7 @@ class AppSettings(object):
def settings(self):
if not hasattr(self, '_settings'):
from django.conf import settings
+
self._settings = settings
return self._settings
@@ -26,16 +27,21 @@ class AppSettings(object):
@property
def DOCBOW_MENU(self):
from django.utils.translation import ugettext_noop
- return getattr(self.settings, 'DOCBOW_MENU', [
- ('send-file-selector', ugettext_noop('send-file_menu')),
- ('inbox', ugettext_noop('inbox_menu')),
- ('outbox', ugettext_noop('outbox_menu')),
- ('docbow_admin:index', ugettext_noop('admin_menu')),
- ('profile', ugettext_noop('profile_menu')),
- ('mailing-lists', ugettext_noop('mailing-lists')),
- ('help', ugettext_noop('help_menu')),
- ('contact', ugettext_noop('contact_menu')),
- ])
+
+ return getattr(
+ self.settings,
+ 'DOCBOW_MENU',
+ [
+ ('send-file-selector', ugettext_noop('send-file_menu')),
+ ('inbox', ugettext_noop('inbox_menu')),
+ ('outbox', ugettext_noop('outbox_menu')),
+ ('docbow_admin:index', ugettext_noop('admin_menu')),
+ ('profile', ugettext_noop('profile_menu')),
+ ('mailing-lists', ugettext_noop('mailing-lists')),
+ ('help', ugettext_noop('help_menu')),
+ ('contact', ugettext_noop('contact_menu')),
+ ],
+ )
@property
def BASE_URL(self):
@@ -47,7 +53,7 @@ class AppSettings(object):
@property
def MAX_FILE_SIZE(self):
- return getattr(self.settings, 'DOCBOW_MAX_FILE_SIZE', 10*1024*1024)
+ return getattr(self.settings, 'DOCBOW_MAX_FILE_SIZE', 10 * 1024 * 1024)
@property
def MIME_BUFFER_SIZE(self):
@@ -55,10 +61,11 @@ class AppSettings(object):
def __getattr__(self, name):
from django.conf import settings
+
if name not in self.__DEFAULTS:
raise AttributeError
- return getattr(settings, self.__prefix + name,
- self.__DEFAULTS[name])
+ return getattr(settings, self.__prefix + name, self.__DEFAULTS[name])
+
import sys
diff --git a/docbow_project/docbow/auth_backend.py b/docbow_project/docbow/auth_backend.py
index dba1004..06f6b14 100644
--- a/docbow_project/docbow/auth_backend.py
+++ b/docbow_project/docbow/auth_backend.py
@@ -2,8 +2,7 @@ from django.contrib.auth.models import User
def set_auth_hash_getter(user, delegate):
- if hasattr(user, 'get_session_auth_hash') \
- and hasattr(delegate, 'get_session_auth_hash'):
+ if hasattr(user, 'get_session_auth_hash') and hasattr(delegate, 'get_session_auth_hash'):
user.get_session_auth_hash = delegate.get_session_auth_hash
@@ -38,7 +37,6 @@ try:
import mellon.backends
class DocbowMellonAuthBackend(mellon.backends.SAMLBackend):
-
def get_user(self, user_id):
try:
delegate = User.objects.get(pk=user_id, docbowprofile__is_guest=True)
@@ -51,5 +49,6 @@ try:
except User.DoesNotExist:
return super(DocbowMellonAuthBackend, self).get_user(user_id)
+
except ImportError:
pass
diff --git a/docbow_project/docbow/auth_urls.py b/docbow_project/docbow/auth_urls.py
index e2610f6..73d2e3b 100644
--- a/docbow_project/docbow/auth_urls.py
+++ b/docbow_project/docbow/auth_urls.py
@@ -8,32 +8,37 @@ from docbow_project.docbow import auth_views as docbow_auth_views
urlpatterns = [
- url(r'^login/$',
- docbow_auth_views.login,
- {'template_name': 'registration/login.html'},
- name='auth_login'),
- url(r'^logout/$',
+ url(
+ r'^login/$', docbow_auth_views.login, {'template_name': 'registration/login.html'}, name='auth_login'
+ ),
+ url(
+ r'^logout/$',
auth_views.LogoutView.as_view(template_name='registration/logout.html'),
- name='auth_logout'),
- url(r'^password/change/$',
- views.password_change,
- name='auth_password_change'),
- url(r'^password/change/done/$',
+ name='auth_logout',
+ ),
+ url(r'^password/change/$', views.password_change, name='auth_password_change'),
+ url(
+ r'^password/change/done/$',
auth_views.PasswordChangeDoneView.as_view(),
- name='auth_password_change_done'),
- url(r'^password/reset/$',
+ name='auth_password_change_done',
+ ),
+ url(
+ r'^password/reset/$',
auth_views.PasswordResetView.as_view(
success_url=reverse_lazy('auth_password_reset_done'),
- form_class=forms.PasswordResetFormWithLogging
+ form_class=forms.PasswordResetFormWithLogging,
),
- name='auth_password_reset'),
- url(r'^password/reset/confirm/(?P[0-9A-Za-z_\-]+)/(?P.+)/$',
+ name='auth_password_reset',
+ ),
+ url(
+ r'^password/reset/confirm/(?P[0-9A-Za-z_\-]+)/(?P.+)/$',
auth_views.PasswordResetConfirmView.as_view(),
- name='auth_password_reset_confirm'),
- url(r'^password/reset/complete/$',
+ name='auth_password_reset_confirm',
+ ),
+ url(
+ r'^password/reset/complete/$',
auth_views.PasswordResetCompleteView.as_view(),
- name='password_reset_complete'),
- url(r'^password/reset/done/$',
- views.password_reset_done,
- name='auth_password_reset_done'),
+ name='password_reset_complete',
+ ),
+ url(r'^password/reset/done/$', views.password_reset_done, name='auth_password_reset_done'),
]
diff --git a/docbow_project/docbow/auth_views.py b/docbow_project/docbow/auth_views.py
index 3de3b24..e6a8562 100644
--- a/docbow_project/docbow/auth_views.py
+++ b/docbow_project/docbow/auth_views.py
@@ -7,6 +7,7 @@ from django.utils.six.moves.urllib import parse as urllib
if 'mellon' in settings.INSTALLED_APPS:
from mellon.utils import get_idps
else:
+
def get_idps():
return []
@@ -15,8 +16,9 @@ def login(request, *args, **kwargs):
if any(get_idps()):
if 'next' not in request.GET:
return HttpResponseRedirect(resolve_url('mellon_login'))
- return HttpResponseRedirect(resolve_url('mellon_login') + '?next='
- + urllib.quote(request.GET.get('next')))
+ return HttpResponseRedirect(
+ resolve_url('mellon_login') + '?next=' + urllib.quote(request.GET.get('next'))
+ )
return auth_views.LoginView.as_view(*args, **kwargs)(request)
diff --git a/docbow_project/docbow/cbv.py b/docbow_project/docbow/cbv.py
index baafa8a..251bb8a 100644
--- a/docbow_project/docbow/cbv.py
+++ b/docbow_project/docbow/cbv.py
@@ -1,4 +1,3 @@
-
class FormWithRequestMixin(object):
def get_form_kwargs(self, **kwargs):
kwargs = super(FormWithRequestMixin, self).get_form_kwargs(**kwargs)
@@ -15,6 +14,7 @@ class FormWithPrefixMixin(object):
kwargs['prefix'] = self.prefix
return kwargs
+
class FormWithPostTarget(FormWithPrefixMixin):
def get_form_kwargs(self, **kwargs):
kwargs = super(FormWithPostTarget, self).get_form_kwargs(**kwargs)
@@ -25,4 +25,3 @@ class FormWithPostTarget(FormWithPrefixMixin):
def is_post_target(self):
return self.prefix + '-validate' in self.request.POST
-
diff --git a/docbow_project/docbow/context_processors.py b/docbow_project/docbow/context_processors.py
index 72a5fd7..fe465e2 100644
--- a/docbow_project/docbow/context_processors.py
+++ b/docbow_project/docbow/context_processors.py
@@ -1,6 +1,7 @@
from django.conf import settings
from django.shortcuts import resolve_url
+
def settings_url_processor(request):
logout_url = settings.LOGOUT_URL
logout_url = resolve_url(logout_url)
diff --git a/docbow_project/docbow/decorators.py b/docbow_project/docbow/decorators.py
index e14106f..32c1f76 100644
--- a/docbow_project/docbow/decorators.py
+++ b/docbow_project/docbow/decorators.py
@@ -9,16 +9,19 @@ from django.utils.decorators import available_attrs
from django.utils.cache import patch_cache_control
from django.views.decorators.cache import never_cache as old_never_cache
+
def no_delegate(view_func):
'''
Forbid delegated account to use this view.
'''
+
@wraps(view_func, assigned=available_attrs(view_func))
def f(request, *args, **kwargs):
if hasattr(request.user, 'delegate'):
messages.warning(request, _('Your delegation does not allow you to do this action'))
return redirect('inbox')
return view_func(request, *args, **kwargs)
+
return f
@@ -27,6 +30,7 @@ def as_delegate(view_func):
Replace the effective user by the real user of the delegate for the
given view.
'''
+
@wraps(view_func, assigned=available_attrs(view_func))
def f(request, *args, **kwargs):
if hasattr(request.user, 'delegate'):
@@ -37,12 +41,14 @@ def as_delegate(view_func):
return out
else:
return view_func(request, *args, **kwargs)
+
return f
def never_cache(view_func):
'''Block client caching in all browsers.'''
view_func = old_never_cache(view_func)
+
@wraps(view_func, assigned=available_attrs(view_func))
def f(request, *args, **kwargs):
result = view_func(request, *args, **kwargs)
@@ -50,4 +56,5 @@ def never_cache(view_func):
patch_cache_control(result, no_store=True)
patch_cache_control(result, must_revalidate=True)
return result
+
return f
diff --git a/docbow_project/docbow/email_utils.py b/docbow_project/docbow/email_utils.py
index f64220a..1a12db6 100644
--- a/docbow_project/docbow/email_utils.py
+++ b/docbow_project/docbow/email_utils.py
@@ -9,12 +9,14 @@ sre = re.compile(r'\?=[ \t]+=\?')
# re pat for MIME encoded_word (without trailing spaces)
mre = re.compile(r'=\?[^?]*?\?[bq]\?[^? \t]*?\?=', re.I)
+
def decode_mime(m):
# substitute matching encoded_word with force_text equiv.
h = decode_header(m.group(0))
u = force_text(make_header(h))
return u
+
def u2u_decode(s):
# utility function for (final) decoding of mime header
# note: resulting string is in one line (no \n within)
@@ -23,4 +25,3 @@ def u2u_decode(s):
s = sre.sub('?==?', s)
u = mre.sub(decode_mime, s)
return u
-
diff --git a/docbow_project/docbow/fields.py b/docbow_project/docbow/fields.py
index 7da46e2..0e82d66 100644
--- a/docbow_project/docbow/fields.py
+++ b/docbow_project/docbow/fields.py
@@ -7,27 +7,32 @@ from docbow_project.docbow import pyuca
from docbow_project.docbow.models import username, MailingList
from docbow_project.docbow.widgets import ForcedValueWidget, FilteredSelectMultiple
+
def order_choices(choices):
'''Sort choices using Unicode collations'''
- return sorted(list(choices),
- key=lambda x: pyuca.collator.sort_key(x[1]))
+ return sorted(list(choices), key=lambda x: pyuca.collator.sort_key(x[1]))
+
def order_field_choices(field):
'''Order choices of this field'''
choices = list(field.choices)
- field.choices = [choice for choice in choices if choice[1].startswith('---')] \
- + order_choices([choice for choice in field.choices if not choice[1].startswith('---')])
+ field.choices = [choice for choice in choices if choice[1].startswith('---')] + order_choices(
+ [choice for choice in field.choices if not choice[1].startswith('---')]
+ )
print(field.choices)
+
class Func2Iter(object):
'''Transform a generator producing function into an iterator'''
+
def __init__(self, func):
self.func = func
def __iter__(self):
return self.func().__iter__()
+
class RecipientField(MultipleChoiceField):
'''Field allowing selection among user or list for recipients'''
@@ -64,12 +69,11 @@ class RecipientField(MultipleChoiceField):
list_choices.append((i, mailing_list.name))
list_choices = order_choices(list_choices)
if list_choices and user_choices:
- choices = list_choices+[('', '---')]+user_choices
+ choices = list_choices + [('', '---')] + user_choices
else:
- choices = list_choices+user_choices
+ choices = list_choices + user_choices
if len(choices) == 1:
- self.widget = ForcedValueWidget(value=[choices[0][0]],
- display_value=choices[0][1])
+ self.widget = ForcedValueWidget(value=[choices[0][0]], display_value=choices[0][1])
else:
self.widget = FilteredSelectMultiple(_('Recipients'), False)
return choices
@@ -80,5 +84,3 @@ class RecipientField(MultipleChoiceField):
if not value:
raise ValidationError(_(u'you must set at least one user recipient or one list recipient...'))
return value
-
-
diff --git a/docbow_project/docbow/forms.py b/docbow_project/docbow/forms.py
index 3c286a8..e2532db 100644
--- a/docbow_project/docbow/forms.py
+++ b/docbow_project/docbow/forms.py
@@ -6,7 +6,7 @@ import logging
import collections
-from django.forms import (ModelForm, Form, Textarea, EmailField, CharField, ModelChoiceField)
+from django.forms import ModelForm, Form, Textarea, EmailField, CharField, ModelChoiceField
from django import forms
from django.contrib.auth.models import User
from django.utils.translation import ugettext as _
@@ -22,8 +22,16 @@ from django_journal import journal as django_journal
from docbow_project.docbow.models import (
- Document, username, MailingList, Content, AttachedFile, AutomaticForwarding, DocbowProfile,
- non_guest_users, is_guest, FileTypeAttachedFileKind
+ Document,
+ username,
+ MailingList,
+ Content,
+ AttachedFile,
+ AutomaticForwarding,
+ DocbowProfile,
+ non_guest_users,
+ is_guest,
+ FileTypeAttachedFileKind,
)
from docbow_project.docbow.widgets import TextInpuWithPredefinedValues, JqueryFileUploadInput
from docbow_project.docbow.fields import RecipientField
@@ -56,8 +64,10 @@ class RecipientForm(object):
self.fields['recipients'].list_qs = list_qs
self.fields['recipients'].reset_choices()
+
class ForwardingForm(RecipientForm, Form):
'''Form for forwarding documents'''
+
recipients = RecipientField(label=_('Recipients'), required=True)
sender = ModelChoiceField(label=_('Sender'), queryset=User.objects.all())
@@ -73,10 +83,12 @@ class ForwardingForm(RecipientForm, Form):
delegations = User.objects.none()
else:
self.default_sender = self.user
- delegations = non_guest_users().filter(
- Q(id=self.user.id) |
- Q(delegations_to__to=self.user)) \
- .order_by('last_name', 'first_name', 'username').distinct()
+ delegations = (
+ non_guest_users()
+ .filter(Q(id=self.user.id) | Q(delegations_to__to=self.user))
+ .order_by('last_name', 'first_name', 'username')
+ .distinct()
+ )
super(ForwardingForm, self).__init__(*args, **kwargs)
if len(delegations) > 1:
self.fields['sender'].queryset = delegations
@@ -99,23 +111,19 @@ def max_filename_length():
max_length = field.max_length
return max_length - len(prefix)
+
class FileForm(RecipientForm, ModelForm):
'''Form for creating a new mailing'''
+
user = None
recipients = RecipientField(label=_('Recipients'))
class Meta:
model = Document
- exclude = ('filetype', 'date', 'to_user', 'to_list', '_timestamp', 'real_sender',
- 'reply_to')
+ exclude = ('filetype', 'date', 'to_user', 'to_list', '_timestamp', 'real_sender', 'reply_to')
class Media:
- css = {
- 'all': (
- 'docbow/css/send-file.css',
- 'docbow/css/send_file_form.css'
- )
- }
+ css = {'all': ('docbow/css/send-file.css', 'docbow/css/send_file_form.css')}
js = ('js/askdirtyform.js', 'js/url-preload.js')
def __init__(self, *args, **kwargs):
@@ -129,10 +137,9 @@ class FileForm(RecipientForm, ModelForm):
if self.reply_to:
doc = self.reply_to
initial['sender'] = kwargs.get('user', None)
- initial['recipients'] = [ 'user-%s' % doc.sender.id ]
+ initial['recipients'] = ['user-%s' % doc.sender.id]
initial['comment'] = u'Re: ' + doc.comment
-
super(FileForm, self).__init__(*args, **kwargs)
self.content_fields = []
if self.attached_file_kinds:
@@ -143,22 +150,24 @@ class FileForm(RecipientForm, ModelForm):
label = attached_file_kind.name
mime_types = attached_file_kind.get_mime_types()
widget = JqueryFileUploadInput(
- max_filename_length=max_filename_length(),
- extensions=mime_types_to_extensions(mime_types),
- attached_file_kind=attached_file_kind)
+ max_filename_length=max_filename_length(),
+ extensions=mime_types_to_extensions(mime_types),
+ attached_file_kind=attached_file_kind,
+ )
self.fields[key] = forms.Field(label=label, widget=widget)
insert_index += 1
else:
attached_file_kind = FileTypeAttachedFileKind(mime_types='*/*')
- self.content_fields = [ ('content', attached_file_kind) ]
+ self.content_fields = [('content', attached_file_kind)]
widget = JqueryFileUploadInput(
- max_filename_length=max_filename_length(),
- attached_file_kind=attached_file_kind)
+ max_filename_length=max_filename_length(), attached_file_kind=attached_file_kind
+ )
self.fields['content'] = forms.Field(label=_('Attached files'), widget=widget)
old_widget = self.fields['comment'].widget
- self.fields['comment'].widget = TextInpuWithPredefinedValues(attrs=old_widget.attrs,
- choices=self.get_predefined_comments())
+ self.fields['comment'].widget = TextInpuWithPredefinedValues(
+ attrs=old_widget.attrs, choices=self.get_predefined_comments()
+ )
if len(self.delegations) > 1:
self.fields['sender'].queryset = self.delegations
self.fields['sender'].label_from_instance = lambda y: username(y)
@@ -177,8 +186,8 @@ class FileForm(RecipientForm, ModelForm):
'''Return a list of predefined comments, structured as choice list for
a form field.
'''
- choices = [ (content.description,)*2 for content in Content.objects.all() ]
- choices.insert(0, ('---','---'))
+ choices = [(content.description,) * 2 for content in Content.objects.all()]
+ choices.insert(0, ('---', '---'))
return choices
def clean(self):
@@ -197,9 +206,9 @@ class FileForm(RecipientForm, ModelForm):
if not attached_file_kind.match_file(upload_file):
mime_types = attached_file_kind.get_mime_types()
file_name = os.path.basename(upload_file.name)
- msg = _(u'The file name "{file_name}" does not match the patterns "{extensions}".').format(
- file_name=file_name,
- extensions=mime_types_to_extensions(mime_types))
+ msg = _(
+ u'The file name "{file_name}" does not match the patterns "{extensions}".'
+ ).format(file_name=file_name, extensions=mime_types_to_extensions(mime_types))
errors.append(msg)
if errors:
self._errors[field] = self.error_class(errors)
@@ -224,19 +233,21 @@ class FileForm(RecipientForm, ModelForm):
upload_id, uploaded_files = self.cleaned_data.get(field, (None, []))
for uploaded_file in uploaded_files:
uploaded_file.name = os.path.basename(uploaded_file.name)
- AttachedFile(document=instance,
- kind=attached_file_kind if attached_file_kind.id else None,
- name=truncate_filename(uploaded_file.name),
- content=uploaded_file).save()
+ AttachedFile(
+ document=instance,
+ kind=attached_file_kind if attached_file_kind.id else None,
+ name=truncate_filename(uploaded_file.name),
+ content=uploaded_file,
+ ).save()
class ContactForm(Form):
'''Form to contact administrators of the platform for logged in users.'''
- subject = forms.CharField(max_length=100, label=_('Subject'),
- required=True)
- message = forms.CharField(widget=Textarea(attrs={'rows': 25, 'cols': 80}),
- label=_('Message'), required=True)
+ subject = forms.CharField(max_length=100, label=_('Subject'), required=True)
+ message = forms.CharField(
+ widget=Textarea(attrs={'rows': 25, 'cols': 80}), label=_('Message'), required=True
+ )
class Media:
js = ('js/askdirtyform.js',)
@@ -247,8 +258,7 @@ class AnonymousContactForm(ContactForm):
name = forms.CharField(max_length=100, label=_('Name'), required=True)
email = forms.EmailField(max_length=100, label=_('Email'), required=False)
- phone_number = forms.CharField(max_length=100, label=_('Phone number'),
- required=False)
+ phone_number = forms.CharField(max_length=100, label=_('Phone number'), required=False)
class MailingListForm(ModelForm):
@@ -258,14 +268,13 @@ class MailingListForm(ModelForm):
model = MailingList
fields = ('name', 'is_active', 'members', 'mailing_list_members')
widgets = {
- 'members': AdminFilteredSelectMultiple(_('Persons'), False),
+ 'members': AdminFilteredSelectMultiple(_('Persons'), False),
}
def __init__(self, *args, **kwargs):
'''Orders members by their username, use their username to display them.'''
ModelForm.__init__(self, *args, **kwargs)
- self.fields['members'].queryset = non_guest_users() \
- .order_by('username')
+ self.fields['members'].queryset = non_guest_users().order_by('username')
self.fields['members'].label_from_instance = lambda y: username(y)
@@ -278,11 +287,11 @@ class UserChoiceField(ModelChoiceField):
class DelegationForm(Form):
'''Form to manager delegations of users'''
+
first_name = CharField(label=_('Firstname'), max_length=30, required=False)
last_name = CharField(label=_('Lastname'), max_length=30, required=False)
email = EmailField(label=_('Email'), required=False)
- existing_user = UserChoiceField(label=_('User'),
- required=False, queryset=User.objects.all())
+ existing_user = UserChoiceField(label=_('User'), required=False, queryset=User.objects.all())
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user', None)
@@ -306,11 +315,17 @@ class DelegationForm(Form):
new = ok1 and ok2 and ok3
ok4 = bool(cleaned_data.get('existing_user'))
if not ((ok1 or ok2 or ok3) ^ ok4):
- raise ValidationError(_('You must choose between creating a new '
- 'user or delegating to an existing one; the two are mutually '
- 'exclusive.'))
+ raise ValidationError(
+ _(
+ 'You must choose between creating a new '
+ 'user or delegating to an existing one; the two are mutually '
+ 'exclusive.'
+ )
+ )
if not new and (ok1 or ok2 or ok3):
- raise ValidationError(_('To create a new user you must give a first name, a last name and a valid email'))
+ raise ValidationError(
+ _('To create a new user you must give a first name, a last name and a valid email')
+ )
if new:
email = cleaned_data.get('email')
if email == self.user.email:
@@ -322,8 +337,11 @@ class DelegationForm(Form):
list_of_names = u', '.join([user.get_full_name() for user in qs])
self.data = {}
self.is_bound = False
- raise ValidationError(_('This email belong to existing user(s) {0}, look in the list of existing users') \
- .format(list_of_names))
+ raise ValidationError(
+ _('This email belong to existing user(s) {0}, look in the list of existing users').format(
+ list_of_names
+ )
+ )
if 'mellon' in app_settings.settings.INSTALLED_APPS:
# Create user
@@ -333,7 +351,7 @@ class DelegationForm(Form):
'last_name': cleaned_data['last_name'],
'email': email,
'send_registration_email': True,
- 'send_registration_email_next_url': self._request.build_absolute_uri('/')
+ 'send_registration_email_next_url': self._request.build_absolute_uri('/'),
}
err, json_data, err_desc = a2_wscall(url, 'post', json)
if err:
@@ -345,7 +363,8 @@ class DelegationForm(Form):
if role_uuid:
url = urllib.parse.urljoin(
app_settings.settings.AUTHENTIC_URL,
- 'api/roles/%s/members/%s/' % (role_uuid, json_data['uuid']))
+ 'api/roles/%s/members/%s/' % (role_uuid, json_data['uuid']),
+ )
err, json_data, err_desc = a2_wscall(url, 'post')
if err:
raise ValidationError(err_desc)
@@ -389,8 +408,10 @@ class ProfileForm(ModelForm):
ModelForm.__init__(self, *args, **kwargs)
if app_settings.MOBILE_PHONE:
- self.fields['mobile_phone'].help_text = _('Use international phone number '
- 'format, i.e +[country code][number]. A challenge SMS will be sent to you to validate it.')
+ self.fields['mobile_phone'].help_text = _(
+ 'Use international phone number '
+ 'format, i.e +[country code][number]. A challenge SMS will be sent to you to validate it.'
+ )
def clean_mobile_phone(self):
'''Validate the mobile phone number by sending a HMAC signature as a code by SMS
@@ -404,22 +425,30 @@ class ProfileForm(ModelForm):
self.cleaned_data['mobile_phone'] = mobile_phone
if not self.instance or self.instance.mobile_phone != mobile_phone:
date = datetime.date.today()
- code = hmac.new(force_bytes(settings.SECRET_KEY), force_text(date) +
- mobile_phone, hashlib.sha1).hexdigest()
+ code = hmac.new(
+ force_bytes(settings.SECRET_KEY), force_text(date) + mobile_phone, hashlib.sha1
+ ).hexdigest()
code = '%06d' % (int(code, 16) % 1000000)
key = '%s-code' % self.prefix if self.prefix else 'code'
if self.data.get(key, '').strip() != code:
+
def send_sms(mobile_phone, code):
try:
sms_carrier = notification.SMSNotifier.get_carrier()
sms_carrier.send_sms((mobile_phone,), 'code is ' + code, no_stop=False)
return True
except Exception:
- logger.exception('unable to send SMS verification code %r to %r',
- code, mobile_phone)
- self.request.record('error', 'unable to send SMS verification code {code} to {mobile_phone}',
- mobile_phone=mobile_phone, code=code)
+ logger.exception(
+ 'unable to send SMS verification code %r to %r', code, mobile_phone
+ )
+ self.request.record(
+ 'error',
+ 'unable to send SMS verification code {code} to {mobile_phone}',
+ mobile_phone=mobile_phone,
+ code=code,
+ )
return False
+
if not send_sms(mobile_phone, code):
raise ValidationError(_('Unable to send you the SMS code, try again.'))
self.fields['code'] = CharField(label='Code')
@@ -470,10 +499,11 @@ class PasswordResetFormWithLogging(PasswordResetForm):
"""
identifier = self.cleaned_data["identifier"]
self.users_cache = User.objects.filter(
- Q(email__iexact=identifier)|
- Q(username=identifier)|
- Q(docbowprofile__personal_email=identifier),
- is_active=True).distinct()
+ Q(email__iexact=identifier)
+ | Q(username=identifier)
+ | Q(docbowprofile__personal_email=identifier),
+ is_active=True,
+ ).distinct()
for user in self.users_cache:
try:
if not user.email or _unicode_ci_compare(user.docbowprofile.personal_email, identifier):
@@ -482,18 +512,28 @@ class PasswordResetFormWithLogging(PasswordResetForm):
pass
self.users_cache = [user for user in self.users_cache if user.email]
if not len(self.users_cache):
- raise forms.ValidationError(_("That e-mail address or identifier doesn't have an associated user account. Are you sure you've registered?"))
+ raise forms.ValidationError(
+ _(
+ "That e-mail address or identifier doesn't have an associated user account. Are you sure you've registered?"
+ )
+ )
return identifier
def get_users(self, *args):
return self.users_cache
- def save(self, domain_override=None,
- subject_template_name='registration/password_reset_subject.txt',
- email_template_name='registration/password_reset_email.html',
- use_https=False, token_generator=default_token_generator,
- from_email=None, request=None, html_email_template_name=None,
- extra_email_context=None):
+ def save(
+ self,
+ domain_override=None,
+ subject_template_name='registration/password_reset_subject.txt',
+ email_template_name='registration/password_reset_email.html',
+ use_https=False,
+ token_generator=default_token_generator,
+ from_email=None,
+ request=None,
+ html_email_template_name=None,
+ extra_email_context=None,
+ ):
"""
Generates a one-use only link for resetting password and sends to the
user.
@@ -519,20 +559,28 @@ class PasswordResetFormWithLogging(PasswordResetForm):
if extra_email_context is not None:
context.update(extra_email_context)
self.send_mail(
- subject_template_name, email_template_name, context, from_email,
- user_email, html_email_template_name=html_email_template_name,
+ subject_template_name,
+ email_template_name,
+ context,
+ from_email,
+ user_email,
+ html_email_template_name=html_email_template_name,
)
for user in self.users_cache:
- django_journal.record('password-reset', 'password reset link sent to {email}', user=user,
- email=user.email, ip=get_extra()['ip'])
+ django_journal.record(
+ 'password-reset',
+ 'password reset link sent to {email}',
+ user=user,
+ email=user.email,
+ ip=get_extra()['ip'],
+ )
class PasswordChangeFormWithLogging(PasswordChangeForm):
def save(self, *args, **kwargs):
super(PasswordChangeFormWithLogging, self).save(*args, **kwargs)
- django_journal.record('password-change', 'changed its email', user=self.user,
- ip=get_extra()['ip'])
+ django_journal.record('password-change', 'changed its email', user=self.user, ip=get_extra()['ip'])
class FilterForm(forms.Form):
@@ -542,11 +590,11 @@ class FilterForm(forms.Form):
class Media:
js = (
- 'jquery-ui/js/jquery-ui-1.12.1-autocomplete-datepicker.min.js',
- 'docbow/js/filter-form.js',
+ 'jquery-ui/js/jquery-ui-1.12.1-autocomplete-datepicker.min.js',
+ 'docbow/js/filter-form.js',
)
css = {
- 'all': ('jquery-ui/css/jquery-ui-1.12.1.css',),
+ 'all': ('jquery-ui/css/jquery-ui-1.12.1.css',),
}
def __init__(self, *args, **kwargs):
@@ -557,27 +605,26 @@ class FilterForm(forms.Form):
for field in ('sort', 'page'):
if field in request.GET:
- self.fields[field] = forms.CharField(
- initial=request.GET.get(field),
- widget=forms.HiddenInput)
+ self.fields[field] = forms.CharField(initial=request.GET.get(field), widget=forms.HiddenInput)
def clean(self):
cleaned_data = super(FilterForm, self).clean()
- if cleaned_data.get('not_before') and cleaned_data.get('not_after') and \
- cleaned_data['not_before'] > cleaned_data['not_after']:
- raise ValidationError(_('From must be inferior or equal to To'))
+ if (
+ cleaned_data.get('not_before')
+ and cleaned_data.get('not_after')
+ and cleaned_data['not_before'] > cleaned_data['not_after']
+ ):
+ raise ValidationError(_('From must be inferior or equal to To'))
return cleaned_data
class EmailForm(ModelForm):
- old_email = forms.EmailField(label=_('Old email'), required=False,
- widget=forms.TextInput(attrs={'disabled': 'on'}))
- password = forms.CharField(label=_("Password"),
- widget=forms.PasswordInput())
+ old_email = forms.EmailField(
+ label=_('Old email'), required=False, widget=forms.TextInput(attrs={'disabled': 'on'})
+ )
+ password = forms.CharField(label=_("Password"), widget=forms.PasswordInput())
email = forms.EmailField(label=_('New email'), required=True, initial='')
- email2 = forms.EmailField(label=_('New email (repeated)'),
- required=True,
- widget=forms.TextInput())
+ email2 = forms.EmailField(label=_('New email (repeated)'), required=True, widget=forms.TextInput())
class Meta:
model = User
@@ -604,7 +651,6 @@ class EmailForm(ModelForm):
class NotificationPreferencesForm(Form):
-
class Media:
js = ('docbow/js/checkall.js',)
@@ -631,12 +677,13 @@ class NotificationPreferencesForm(Form):
choices=self.choices,
initial=self.initials[filetype.id],
widget=widgets.CheckboxMultipleSelect,
- required=False)
+ required=False,
+ )
def save(self):
cleaned_data = self.cleaned_data
- adds = collections.defaultdict(lambda:[])
- removes = collections.defaultdict(lambda:[])
+ adds = collections.defaultdict(lambda: [])
+ removes = collections.defaultdict(lambda: [])
for key in cleaned_data:
filetype_id = int(key.split('-')[1])
new = set(cleaned_data[key])
@@ -648,15 +695,11 @@ class NotificationPreferencesForm(Form):
adds[kind].append(filetype_id)
for kind in adds:
models.NotificationPreference.objects.filter(
- user=self.user,
- kind=kind,
- filetype__in=adds[kind]).delete()
+ user=self.user, kind=kind, filetype__in=adds[kind]
+ ).delete()
for kind in removes:
for filetype_id in removes[kind]:
filetype = models.FileType.objects.get(id=filetype_id)
- np, created = models.NotificationPreference \
- .objects.get_or_create(
- user=self.user,
- kind=kind,
- filetype=filetype,
- value=False)
+ np, created = models.NotificationPreference.objects.get_or_create(
+ user=self.user, kind=kind, filetype=filetype, value=False
+ )
diff --git a/docbow_project/docbow/management/commands/add-list.py b/docbow_project/docbow/management/commands/add-list.py
index b707142..2b72323 100644
--- a/docbow_project/docbow/management/commands/add-list.py
+++ b/docbow_project/docbow/management/commands/add-list.py
@@ -15,37 +15,29 @@ def get_object(model, ref):
else:
return model.objects.get(name=ref)
+
class Command(BaseCommand):
help = '''Create or update a list'''
def add_arguments(self, parser):
+ parser.add_argument('ml_name', type=str, help='Name of the mailing list')
parser.add_argument(
- 'ml_name', type=str,
- help='Name of the mailing list')
- parser.add_argument(
- "--add-list", action="append",
- help='add a list as a sublist', default=[],
+ "--add-list", action="append", help='add a list as a sublist', default=[],
)
parser.add_argument(
- "--remove-list", action="append",
- help='remove list as a sublist', default=[],
- )
- parser.add_argument(
- "--add-user", action="append",
- help='add a user member', default=[]
- )
- parser.add_argument(
- "--remove-user", action="append",
- help='remove a user member', default=[]
+ "--remove-list", action="append", help='remove list as a sublist', default=[],
)
+ parser.add_argument("--add-user", action="append", help='add a user member', default=[])
+ parser.add_argument("--remove-user", action="append", help='remove a user member', default=[])
@transaction.atomic
def handle(self, **options):
locale.setlocale(locale.LC_ALL, '')
locale_encoding = locale.nl_langinfo(locale.CODESET)
mailing_list, created = MailingList.objects.get_or_create(
- name=force_text(options['ml_name'], locale_encoding))
+ name=force_text(options['ml_name'], locale_encoding)
+ )
try:
for l in options['add_list']:
l = get_object(MailingList, l)
@@ -54,7 +46,7 @@ class Command(BaseCommand):
l = get_object(MailingList, l)
mailing_list.mailing_list_members.remove(l)
except MailingList.DoesNotExist:
- raise CommandError('list %r does not exist' % l)
+ raise CommandError('list %r does not exist' % l)
try:
for g in options['add_user']:
g = get_object(User, g)
diff --git a/docbow_project/docbow/management/commands/add-user.py b/docbow_project/docbow/management/commands/add-user.py
index 6c366ae..55ae097 100644
--- a/docbow_project/docbow/management/commands/add-user.py
+++ b/docbow_project/docbow/management/commands/add-user.py
@@ -15,6 +15,7 @@ def get_object(model, ref):
else:
return model.objects.get(name=ref)
+
class Command(BaseCommand):
args = ''
help = '''Create a new user or update an existing user
@@ -23,31 +24,25 @@ List and groups can be referred by name or by id.
'''
option_list = BaseCommand.option_list + (
- make_option("--first-name", help='set first name'),
- make_option("--last-name", help='set last name'),
- make_option("--email", help='set email'),
- make_option("--mobile-phone",
- help='set mobile phone used for SMS notifications'),
- make_option("--personal-email", help='set personal email'),
- make_option("--add-list",
- help='add user to list', action="append", default=[]),
- make_option("--add-group",
- help='add user to group', action="append", default=[]),
- make_option("--remove-list",
- help='remove user from list', action="append", default=[]),
- make_option("--remove-group",
- help='remove user from group', action="append", default=[]),
- make_option("--activate", action="store_true",
- help='activate the user (default at creation)', default=None),
- make_option("--deactivate", dest='activate', action="store_false",
- help='deactivate the user'),
- make_option("--superuser", action="store_true",
- help='set the superuser flag', default=None),
- make_option("--no-superuser", dest='superuser',
- action="store_false", help='unset the superuser flag'),
+ make_option("--first-name", help='set first name'),
+ make_option("--last-name", help='set last name'),
+ make_option("--email", help='set email'),
+ make_option("--mobile-phone", help='set mobile phone used for SMS notifications'),
+ make_option("--personal-email", help='set personal email'),
+ make_option("--add-list", help='add user to list', action="append", default=[]),
+ make_option("--add-group", help='add user to group', action="append", default=[]),
+ make_option("--remove-list", help='remove user from list', action="append", default=[]),
+ make_option("--remove-group", help='remove user from group', action="append", default=[]),
+ make_option(
+ "--activate", action="store_true", help='activate the user (default at creation)', default=None
+ ),
+ make_option("--deactivate", dest='activate', action="store_false", help='deactivate the user'),
+ make_option("--superuser", action="store_true", help='set the superuser flag', default=None),
+ make_option(
+ "--no-superuser", dest='superuser', action="store_false", help='unset the superuser flag'
+ ),
)
-
@transaction.atomic
def handle(self, *args, **options):
if len(args) != 1:
@@ -71,7 +66,7 @@ List and groups can be referred by name or by id.
l = get_object(MailingList, l)
l.members.remove(user)
except MailingList.DoesNotExist:
- raise CommandError('list %r does not exist' % l)
+ raise CommandError('list %r does not exist' % l)
try:
for g in options['add_group']:
g = get_object(Group, g)
diff --git a/docbow_project/docbow/management/commands/archive.py b/docbow_project/docbow/management/commands/archive.py
index f654a11..e315fb7 100644
--- a/docbow_project/docbow/management/commands/archive.py
+++ b/docbow_project/docbow/management/commands/archive.py
@@ -14,6 +14,7 @@ from django.conf import settings
from ... import models
from ....log import models as log_models
+
class Command(BaseCommand):
args = ''
help = 'Save logs, and user list'
@@ -24,12 +25,7 @@ class Command(BaseCommand):
def save_users(self, path):
with open(os.path.join(path, 'users.csv'), 'w') as f:
- headers = ['username',
- 'prenom',
- 'nom',
- 'email',
- 'profil',
- 'groupe']
+ headers = ['username', 'prenom', 'nom', 'email', 'profil', 'groupe']
csv_handle = csv.DictWriter(f, headers)
users = auth_models.User.objects.filter(is_superuser=False)
csv_handle.writerow(dict(zip(csv_handle.fieldnames, csv_handle.fieldnames)))
@@ -42,19 +38,15 @@ class Command(BaseCommand):
'nom': user.last_name,
'email': user.email,
'profil': ','.join([ml.name for ml in user.mailing_lists.all()]),
- 'groupe': ','.join([group.name for group in user.groups.all()])}
+ 'groupe': ','.join([group.name for group in user.groups.all()]),
+ }
self.dict_to_utf8(d)
csv_handle.writerow(d)
users.delete()
def save_logs(self, path):
with open(os.path.join(path, 'log.csv'), 'w') as f:
- headers = ['timestamp',
- 'name',
- 'levelname',
- 'ip',
- 'user',
- 'message']
+ headers = ['timestamp', 'name', 'levelname', 'ip', 'user', 'message']
csv_handle = csv.DictWriter(f, headers)
csv_handle.writerow(dict(zip(csv_handle.fieldnames, csv_handle.fieldnames)))
logs = log_models.LogLine.objects.all()
diff --git a/docbow_project/docbow/management/commands/clean-documents.py b/docbow_project/docbow/management/commands/clean-documents.py
index a598665..ff6835d 100644
--- a/docbow_project/docbow/management/commands/clean-documents.py
+++ b/docbow_project/docbow/management/commands/clean-documents.py
@@ -2,8 +2,10 @@ from __future__ import print_function
from django.core.management.base import BaseCommand
from ... import models
+
class Command(BaseCommand):
'''Undelete all documents'''
+
help = 'Undelete all documents'
def handle(self, *args, **options):
diff --git a/docbow_project/docbow/management/commands/docbow_dumpdata.py b/docbow_project/docbow/management/commands/docbow_dumpdata.py
index feb9287..b33971a 100644
--- a/docbow_project/docbow/management/commands/docbow_dumpdata.py
+++ b/docbow_project/docbow/management/commands/docbow_dumpdata.py
@@ -6,25 +6,60 @@ from django.utils.datastructures import SortedDict
from optparse import make_option
+
class Command(BaseCommand):
option_list = BaseCommand.option_list + (
- make_option('--format', default='json', dest='format',
- help='Specifies the output serialization format for fixtures.'),
- make_option('--indent', default=None, dest='indent', type='int',
- help='Specifies the indent level to use when pretty-printing output'),
- make_option('--database', action='store', dest='database',
- default=DEFAULT_DB_ALIAS, help='Nominates a specific database to dump '
- 'fixtures from. Defaults to the "default" database.'),
- make_option('-e', '--exclude', dest='exclude',action='append', default=[],
- help='An appname or appname.ModelName to exclude (use multiple --exclude to exclude multiple apps/models).'),
- make_option('-n', '--natural', action='store_true', dest='use_natural_keys', default=False,
- help='Use natural keys if they are available.'),
- make_option('-a', '--all', action='store_true', dest='use_base_manager', default=False,
- help="Use Django's base manager to dump all models stored in the database, including those that would otherwise be filtered or modified by a custom manager."),
+ make_option(
+ '--format',
+ default='json',
+ dest='format',
+ help='Specifies the output serialization format for fixtures.',
+ ),
+ make_option(
+ '--indent',
+ default=None,
+ dest='indent',
+ type='int',
+ help='Specifies the indent level to use when pretty-printing output',
+ ),
+ make_option(
+ '--database',
+ action='store',
+ dest='database',
+ default=DEFAULT_DB_ALIAS,
+ help='Nominates a specific database to dump '
+ 'fixtures from. Defaults to the "default" database.',
+ ),
+ make_option(
+ '-e',
+ '--exclude',
+ dest='exclude',
+ action='append',
+ default=[],
+ help='An appname or appname.ModelName to exclude (use multiple --exclude to exclude multiple apps/models).',
+ ),
+ make_option(
+ '-n',
+ '--natural',
+ action='store_true',
+ dest='use_natural_keys',
+ default=False,
+ help='Use natural keys if they are available.',
+ ),
+ make_option(
+ '-a',
+ '--all',
+ action='store_true',
+ dest='use_base_manager',
+ default=False,
+ help="Use Django's base manager to dump all models stored in the database, including those that would otherwise be filtered or modified by a custom manager.",
+ ),
+ )
+ help = (
+ "Output the contents of the database as a fixture of the given "
+ "format (using each model's default manager unless --all is "
+ "specified)."
)
- help = ("Output the contents of the database as a fixture of the given "
- "format (using each model's default manager unless --all is "
- "specified).")
args = '[appname appname.ModelName ...]'
def handle(self, *app_labels, **options):
@@ -55,7 +90,11 @@ class Command(BaseCommand):
raise CommandError('Unknown app in excludes: %s' % exclude)
if len(app_labels) == 0:
- app_list = SortedDict((app, [ model for model in get_models(app) if model not in excluded_models ]) for app in get_apps() if app not in excluded_apps)
+ app_list = SortedDict(
+ (app, [model for model in get_models(app) if model not in excluded_models])
+ for app in get_apps()
+ if app not in excluded_apps
+ )
else:
app_list = SortedDict()
for label in app_labels:
@@ -110,13 +149,15 @@ class Command(BaseCommand):
objects.extend(model._default_manager.using(using).all())
try:
- return serializers.serialize(format, objects, indent=indent,
- use_natural_foreign_keys=use_natural_keys)
+ return serializers.serialize(
+ format, objects, indent=indent, use_natural_foreign_keys=use_natural_keys
+ )
except Exception as e:
if show_traceback:
raise
raise CommandError("Unable to serialize database: %s" % e)
+
def sort_dependencies(app_list):
"""Sort a list of app,modellist pairs into a single list of models.
@@ -125,6 +166,7 @@ def sort_dependencies(app_list):
dependency has it's dependencies serialized first.
"""
from django.db.models import get_model, get_models
+
# Process the list of models, and get the list of dependencies
model_dependencies = []
models = set()
@@ -186,9 +228,12 @@ def sort_dependencies(app_list):
else:
skipped.append((model, deps))
if not changed:
- raise CommandError("Can't resolve dependencies for %s in serialized app list." %
- ', '.join('%s.%s' % (model._meta.app_label, model._meta.object_name)
- for model, deps in sorted(skipped, key=lambda obj: obj[0].__name__))
+ raise CommandError(
+ "Can't resolve dependencies for %s in serialized app list."
+ % ', '.join(
+ '%s.%s' % (model._meta.app_label, model._meta.object_name)
+ for model, deps in sorted(skipped, key=lambda obj: obj[0].__name__)
+ )
)
model_dependencies = skipped
diff --git a/docbow_project/docbow/management/commands/dump-users-csv.py b/docbow_project/docbow/management/commands/dump-users-csv.py
index 96273bb..8e15480 100644
--- a/docbow_project/docbow/management/commands/dump-users-csv.py
+++ b/docbow_project/docbow/management/commands/dump-users-csv.py
@@ -6,6 +6,7 @@ from django.db import transaction
from ... import models
+
class Command(BaseCommand):
args = ''
help = 'Dump user list as CSV'
@@ -16,13 +17,7 @@ class Command(BaseCommand):
def save_users(self, path):
with open(path, 'w') as f:
- headers = ['username',
- 'password',
- 'prenom',
- 'nom',
- 'email',
- 'profil',
- 'groupe']
+ headers = ['username', 'password', 'prenom', 'nom', 'email', 'profil', 'groupe']
csv_handle = csv.DictWriter(f, headers)
users = auth_models.User.objects.filter(is_superuser=False, delegations_by__isnull=True)
csv_handle.writerow(dict(zip(csv_handle.fieldnames, csv_handle.fieldnames)))
@@ -36,7 +31,8 @@ class Command(BaseCommand):
'email': user.email,
'password': user.password,
'profil': ','.join([ml.name for ml in user.mailing_lists.all()]),
- 'groupe': ','.join([group.name for group in user.groups.all()])}
+ 'groupe': ','.join([group.name for group in user.groups.all()]),
+ }
self.dict_to_utf8(d)
csv_handle.writerow(d)
diff --git a/docbow_project/docbow/management/commands/empty-trash.py b/docbow_project/docbow/management/commands/empty-trash.py
index 002b584..3ab6db1 100644
--- a/docbow_project/docbow/management/commands/empty-trash.py
+++ b/docbow_project/docbow/management/commands/empty-trash.py
@@ -14,7 +14,8 @@ class Command(BaseCommand):
@transaction.atomic
def handle(self, *args, **kwargs):
target_date = now() - timedelta(days=settings.TRASH_DURATION)
- for deleted_doc in DeletedDocument.objects.filter(soft_delete=True)\
- .filter(soft_delete_date__lte=target_date):
+ for deleted_doc in DeletedDocument.objects.filter(soft_delete=True).filter(
+ soft_delete_date__lte=target_date
+ ):
deleted_doc.soft_delete = False
deleted_doc.save()
diff --git a/docbow_project/docbow/management/commands/forward-docs.py b/docbow_project/docbow/management/commands/forward-docs.py
index c6449cc..7e5a35a 100644
--- a/docbow_project/docbow/management/commands/forward-docs.py
+++ b/docbow_project/docbow/management/commands/forward-docs.py
@@ -25,25 +25,26 @@ class Command(BaseCommand):
parser.add_argument('from_user', type=int)
parser.add_argument('to_user', type=int)
parser.add_argument(
- '-s', '--startdate', required=False, type=valid_date,
- help='The start date - format YYYY-MM-DD'
+ '-s', '--startdate', required=False, type=valid_date, help='The start date - format YYYY-MM-DD'
)
parser.add_argument(
- '-e', '--enddate', required=False, type=valid_date,
- help='The end date - format YYYY-MM-DD'
+ '-e', '--enddate', required=False, type=valid_date, help='The end date - format YYYY-MM-DD'
)
@transaction.atomic
def handle(self, from_user, to_user, *args, **kwargs):
- verbose = (kwargs.get('verbosity') > 1)
+ verbose = kwargs.get('verbosity') > 1
from_user = User.objects.get(pk=from_user)
to_user = User.objects.get(pk=to_user)
from_user_inboxes = Inbox.objects.filter(owner=from_user, outbox=False)
to_user_inboxes = Inbox.objects.filter(owner=to_user, outbox=False)
- docs = Document.objects.exclude(deleteddocument__user=from_user) \
- .filter(mailboxes__in=from_user_inboxes).exclude(mailboxes__in=to_user_inboxes)\
+ docs = (
+ Document.objects.exclude(deleteddocument__user=from_user)
+ .filter(mailboxes__in=from_user_inboxes)
+ .exclude(mailboxes__in=to_user_inboxes)
.distinct()
+ )
startdate, enddate = kwargs.get('startdate'), kwargs.get('enddate')
if startdate:
diff --git a/docbow_project/docbow/management/commands/list-lists.py b/docbow_project/docbow/management/commands/list-lists.py
index 89405ad..2fc3c94 100644
--- a/docbow_project/docbow/management/commands/list-lists.py
+++ b/docbow_project/docbow/management/commands/list-lists.py
@@ -10,38 +10,41 @@ from django.utils.encoding import force_text
from ...models import MailingList
from ...unicodecsv import UnicodeWriter
+
def print_table(table):
col_width = [max(len(x) for x in col) for col in zip(*table)]
for line in table:
- line = u"| " + u" | ".join(u"{0:>{1}}".format(x, col_width[i])
- for i, x in enumerate(line)) + u" |"
+ line = u"| " + u" | ".join(u"{0:>{1}}".format(x, col_width[i]) for i, x in enumerate(line)) + u" |"
print(line)
+
class Command(BaseCommand):
args = ''
help = '''List mailing lists'''
- option_list = BaseCommand.option_list + (
- make_option("--csv", action='store_true'),
- )
+ option_list = BaseCommand.option_list + (make_option("--csv", action='store_true'),)
@transaction.atomic
def handle(self, *args, **options):
locale.setlocale(locale.LC_ALL, '')
locale_encoding = locale.nl_langinfo(locale.CODESET)
- mailing_lists = MailingList.objects.prefetch_related('members',
- 'mailing_list_members')
+ mailing_lists = MailingList.objects.prefetch_related('members', 'mailing_list_members')
for arg in args:
key, value = arg.split('=')
- mailing_lists = mailing_lists.filter(
- **{key: value})
+ mailing_lists = mailing_lists.filter(**{key: value})
tables = [('Id', 'Name', 'Members', 'List Members')]
for mailing_list in mailing_lists:
- tables.append(map(force_text, (
- mailing_list.id,
- mailing_list.name,
- ','.join(m.name for m in mailing_list.mailing_list_members.all()),
- ','.join(g.username for g in mailing_list.members.all()))))
+ tables.append(
+ map(
+ force_text,
+ (
+ mailing_list.id,
+ mailing_list.name,
+ ','.join(m.name for m in mailing_list.mailing_list_members.all()),
+ ','.join(g.username for g in mailing_list.members.all()),
+ ),
+ )
+ )
if options['csv']:
writer = UnicodeWriter(sys.stdout, encoding=locale_encoding)
for row in tables:
diff --git a/docbow_project/docbow/management/commands/list-users.py b/docbow_project/docbow/management/commands/list-users.py
index 03dd5a3..895167d 100644
--- a/docbow_project/docbow/management/commands/list-users.py
+++ b/docbow_project/docbow/management/commands/list-users.py
@@ -11,31 +11,42 @@ from django.utils.encoding import force_text
from ...models import DocbowProfile
from ...unicodecsv import UnicodeWriter
+
def print_table(table):
col_width = [max(len(x) for x in col) for col in zip(*table)]
for line in table:
- line = u"| " + u" | ".join(u"{0:>{1}}".format(x, col_width[i])
- for i, x in enumerate(line)) + u" |"
+ line = u"| " + u" | ".join(u"{0:>{1}}".format(x, col_width[i]) for i, x in enumerate(line)) + u" |"
print(line)
+
class Command(BaseCommand):
args = ''
help = '''List users'''
- option_list = BaseCommand.option_list + (
- make_option("--csv", action='store_true'),
- )
+ option_list = BaseCommand.option_list + (make_option("--csv", action='store_true'),)
@transaction.atomic
def handle(self, *args, **options):
locale.setlocale(locale.LC_ALL, '')
- users = User.objects.prefetch_related('docbowprofile', 'groups',
- 'mailing_lists')
+ users = User.objects.prefetch_related('docbowprofile', 'groups', 'mailing_lists')
for arg in args:
key, value = arg.split('=')
users = users.filter(**{key: value})
- tables = [('Id', 'Username', 'First name', 'Last name', 'Email',
- 'Mobile phone', 'Personal mail', 'Lists', 'Groups', 'Active', 'Superuser')]
+ tables = [
+ (
+ 'Id',
+ 'Username',
+ 'First name',
+ 'Last name',
+ 'Email',
+ 'Mobile phone',
+ 'Personal mail',
+ 'Lists',
+ 'Groups',
+ 'Active',
+ 'Superuser',
+ )
+ ]
for user in users:
try:
mobile_phone = user.docbowprofile.mobile_phone
@@ -43,24 +54,27 @@ class Command(BaseCommand):
except DocbowProfile.DoesNotExist:
mobile_phone = ''
personal_email = ''
- tables.append(map(force_text, (
- user.id,
- user.username,
- user.first_name,
- user.last_name,
- user.email,
- mobile_phone,
- personal_email,
- ','.join(m.name for m in user.mailing_lists.all()),
- ','.join(g.name for g in user.groups.all()),
- user.is_active,
- user.is_superuser)))
+ tables.append(
+ map(
+ force_text,
+ (
+ user.id,
+ user.username,
+ user.first_name,
+ user.last_name,
+ user.email,
+ mobile_phone,
+ personal_email,
+ ','.join(m.name for m in user.mailing_lists.all()),
+ ','.join(g.name for g in user.groups.all()),
+ user.is_active,
+ user.is_superuser,
+ ),
+ )
+ )
if options['csv']:
writer = UnicodeWriter(sys.stdout, encoding=locale.nl_langinfo(locale.CODESET))
for row in tables:
writer.writerow(row)
else:
print_table(tables)
-
-
-
diff --git a/docbow_project/docbow/management/commands/load-users-csv.py b/docbow_project/docbow/management/commands/load-users-csv.py
index 4937f6e..9b57e52 100644
--- a/docbow_project/docbow/management/commands/load-users-csv.py
+++ b/docbow_project/docbow/management/commands/load-users-csv.py
@@ -14,16 +14,16 @@ from ... import models
def strip_accents(s):
- return ''.join((c for c in unicodedata.normalize('NFD', s)
- if unicodedata.category(c) != 'Mn'))
+ return ''.join((c for c in unicodedata.normalize('NFD', s) if unicodedata.category(c) != 'Mn'))
+
def keep_letters(s):
return ''.join([c for c in s if c.isalpha()])
+
def unicode_csv_reader(utf8_csv_data, dialect=csv.excel, **kwargs):
# csv.py doesn't do Unicode; encode temporarily as UTF-8:
- csv_reader = csv.reader(utf8_csv_data,
- dialect=dialect, **kwargs)
+ csv_reader = csv.reader(utf8_csv_data, dialect=dialect, **kwargs)
for row in csv_reader:
# decode UTF-8 back to Unicode, cell by cell:
yield [force_text(cell, 'utf-8') for cell in row]
@@ -32,32 +32,37 @@ def unicode_csv_reader(utf8_csv_data, dialect=csv.excel, **kwargs):
def csv_to_list(s):
return filter(None, map(six.text_type.strip, s.split(u',')))
+
# Utilise seulement des majuscules et des chiffres, sauf i,l et 1, O et 0
__pwd_alphabet = 'ABCDEFGHJKMNPQRSTUVWXYZ23456789'
+
+
def create_password(pwd_length=8):
- password = ''.join([random.choice(__pwd_alphabet)
- for x in range(pwd_length)])
+ password = ''.join([random.choice(__pwd_alphabet) for x in range(pwd_length)])
return password
+
class Command(BaseCommand):
args = '[--profile default_profile1,default_profile2] [--group defaut_group1,default_group2] [--password default_password] [--generate-password] file.csv'
help = 'Load a CSV file containg user definitions'
option_list = BaseCommand.option_list + (
- make_option("--profile", action='append', default=[]),
- make_option("--group", action='append', default=[]),
- make_option("--password", action='store'),
- make_option("--activate", action='store_true'),
- make_option("--generate-password", action='store_true', dest='generate_password'),
- )
+ make_option("--profile", action='append', default=[]),
+ make_option("--group", action='append', default=[]),
+ make_option("--password", action='store'),
+ make_option("--activate", action='store_true'),
+ make_option("--generate-password", action='store_true', dest='generate_password'),
+ )
- headers = { 'nom': 'last_name',
- 'prenom': 'first_name',
- 'email': 'email',
- 'profil': None,
- 'username': None,
- 'groupe': None,
- 'password': None }
+ headers = {
+ 'nom': 'last_name',
+ 'prenom': 'first_name',
+ 'email': 'email',
+ 'profil': None,
+ 'username': None,
+ 'groupe': None,
+ 'password': None,
+ }
def synthesis(self, data, **options):
if not data.get('username'):
@@ -126,8 +131,9 @@ class Command(BaseCommand):
user_profiles = map(profiles.get, user['profil'])
user_instance.mailing_lists = user_profiles
if user['groupe']:
- user_groups = map(lambda x: auth_models.Group.objects.get_or_create(name=x)[0],
- user['groupe'])
+ user_groups = map(
+ lambda x: auth_models.Group.objects.get_or_create(name=x)[0], user['groupe']
+ )
user_instance.groups = user_groups
user_instance.is_staff = reduce(bool.__or__, ['Administrateur' in x for x in user['groupe']])
if user.get('password'):
diff --git a/docbow_project/docbow/management/commands/notify.py b/docbow_project/docbow/management/commands/notify.py
index 14584eb..b7e2225 100644
--- a/docbow_project/docbow/management/commands/notify.py
+++ b/docbow_project/docbow/management/commands/notify.py
@@ -3,6 +3,7 @@ from django.db import transaction
from ... import notification
+
class Command(BaseCommand):
args = ''
help = 'Send notifications'
diff --git a/docbow_project/docbow/management/commands/sendfile.py b/docbow_project/docbow/management/commands/sendfile.py
index be5f220..aa3094d 100644
--- a/docbow_project/docbow/management/commands/sendfile.py
+++ b/docbow_project/docbow/management/commands/sendfile.py
@@ -8,8 +8,7 @@ from django.db import transaction
from django.core.files import File
from django.utils.encoding import force_text
-from docbow_project.docbow.models import (MailingList, FileType, Document,
- AttachedFile)
+from docbow_project.docbow.models import MailingList, FileType, Document, AttachedFile
def get_object(model, ref, name='name'):
@@ -25,9 +24,7 @@ class Command(BaseCommand):
help = '''Send a document'''
def add_arguments(self, parser):
- parser.add_argument(
- 'file_tosend', nargs='+', type=str,
- help='File to send')
+ parser.add_argument('file_tosend', nargs='+', type=str, help='File to send')
parser.add_argument("--sender")
parser.add_argument("--to-list", action="append")
parser.add_argument("--to-user", action="append")
@@ -41,8 +38,7 @@ class Command(BaseCommand):
if 'sender' not in options:
raise CommandError('missing --sender parameter')
try:
- sender = get_object(User,
- force_text(options['sender'], locale_encoding), 'username')
+ sender = get_object(User, force_text(options['sender'], locale_encoding), 'username')
except User.DoesNotExist:
raise CommandError('user %r does not exist' % options['sender'])
to_lists = []
@@ -62,14 +58,14 @@ class Command(BaseCommand):
if 'filetype' not in options:
raise CommandError('missing --filetype parameter')
try:
- filetype = get_object(FileType,
- force_text(options['filetype'], locale_encoding))
+ filetype = get_object(FileType, force_text(options['filetype'], locale_encoding))
except FileType.DoesNotExist:
raise CommandError('filetype %r does not exist' % options['filetype'])
if not to_users and not to_lists:
print(to_users, to_lists, options)
- raise CommandError('you must specify at least one list or user '
- 'recipient using --to-list and --to-user.')
+ raise CommandError(
+ 'you must specify at least one list or user ' 'recipient using --to-list and --to-user.'
+ )
document = Document(sender=sender, filetype=filetype)
document.save()
document.to_user.set(to_users)
@@ -77,6 +73,7 @@ class Command(BaseCommand):
for arg in options['file_tosend']:
if not os.path.isfile(arg):
raise CommandError('file %r does not exist')
- AttachedFile.objects.create(name=force_text(arg, locale_encoding),
- content=File(open(arg)), document=document)
+ AttachedFile.objects.create(
+ name=force_text(arg, locale_encoding), content=File(open(arg)), document=document
+ )
document.post()
diff --git a/docbow_project/docbow/middleware.py b/docbow_project/docbow/middleware.py
index 5152e22..482fced 100644
--- a/docbow_project/docbow/middleware.py
+++ b/docbow_project/docbow/middleware.py
@@ -11,12 +11,14 @@ NO_IP = NO_USER
logger = logging.getLogger('docbow')
+
def get_extra():
'''Extract current remote ip and current user from the thread local storage
from the KeepUserAroundMiddleware middleware class.
'''
k = KeepUserAroundMiddleware
- return { 'ip': k.get_global_ip(), 'user': k.get_global_user() }
+ return {'ip': k.get_global_ip(), 'user': k.get_global_user()}
+
class KeepUserAroundMiddleware(MiddlewareMixin):
'''
@@ -24,6 +26,7 @@ class KeepUserAroundMiddleware(MiddlewareMixin):
variable, so that logging calls inside signals handler can know about
them.
'''
+
__middleware_ctx = threading.local()
__middleware_ctx.user = NO_USER
__middleware_ctx.ip = NO_USER
@@ -39,14 +42,16 @@ class KeepUserAroundMiddleware(MiddlewareMixin):
return response
def process_exception(self, request, exception):
- logger.error('Internal Server Error: %s' % request.path,
+ logger.error(
+ 'Internal Server Error: %s' % request.path,
exc_info=sys.exc_info,
extra={
'status_code': 500,
'request': request,
'ip': self.get_global_ip(),
'user': self.get_global_user(),
- })
+ },
+ )
self.__middleware_ctx.user = NO_USER
self.__middleware_ctx.ip = NO_IP
return None
diff --git a/docbow_project/docbow/migrations/0001_initial.py b/docbow_project/docbow/migrations/0001_initial.py
index d8f9117..e4f8340 100644
--- a/docbow_project/docbow/migrations/0001_initial.py
+++ b/docbow_project/docbow/migrations/0001_initial.py
@@ -20,18 +20,30 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='AttachedFile',
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ (
+ 'id',
+ models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+ ),
('name', models.CharField(max_length=300, verbose_name='Name')),
- ('content', models.FileField(upload_to=docbow_project.docbow.models.generate_filename, max_length=300, verbose_name='File')),
+ (
+ 'content',
+ models.FileField(
+ upload_to=docbow_project.docbow.models.generate_filename,
+ max_length=300,
+ verbose_name='File',
+ ),
+ ),
],
- options={
- },
+ options={},
bases=(models.Model,),
),
migrations.CreateModel(
name='AutomaticForwarding',
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ (
+ 'id',
+ models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+ ),
],
options={
'verbose_name': 'Automatic forwarding rule',
@@ -42,7 +54,10 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='Content',
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ (
+ 'id',
+ models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+ ),
('description', models.CharField(unique=True, max_length=128)),
],
options={
@@ -55,9 +70,28 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='Delegation',
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('by', models.ForeignKey(related_name='delegations_to', verbose_name='From', to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)),
- ('to', models.ForeignKey(related_name='delegations_by', verbose_name='To', to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)),
+ (
+ 'id',
+ models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+ ),
+ (
+ 'by',
+ models.ForeignKey(
+ related_name='delegations_to',
+ verbose_name='From',
+ to=settings.AUTH_USER_MODEL,
+ on_delete=models.CASCADE,
+ ),
+ ),
+ (
+ 'to',
+ models.ForeignKey(
+ related_name='delegations_by',
+ verbose_name='To',
+ to=settings.AUTH_USER_MODEL,
+ on_delete=models.CASCADE,
+ ),
+ ),
],
options={
'ordering': ['by'],
@@ -70,7 +104,10 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='DeletedDocument',
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ (
+ 'id',
+ models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+ ),
],
options={
'ordering': ('-document',),
@@ -82,36 +119,74 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='DeletedMailbox',
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ (
+ 'id',
+ models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+ ),
('delegate', models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)),
],
- options={
- },
+ options={},
bases=(models.Model,),
),
migrations.CreateModel(
name='DocbowProfile',
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ (
+ 'id',
+ models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+ ),
('is_guest', models.BooleanField(default=False, verbose_name='Guest user')),
- ('mobile_phone', models.CharField(blank=True, max_length=32, verbose_name='Mobile phone', validators=[django.core.validators.RegexValidator('^\\+\\d+$')])),
- ('personal_email', models.EmailField(help_text='if you provide a personal email address, notifications of new documents will also be sent to this address.', max_length=75, verbose_name='personal email address', blank=True)),
- ('accept_notifications', models.BooleanField(default=True, help_text='If unchecked you will not received notifications anymore, by email or SMS.', verbose_name='Accept to be notified')),
+ (
+ 'mobile_phone',
+ models.CharField(
+ blank=True,
+ max_length=32,
+ verbose_name='Mobile phone',
+ validators=[django.core.validators.RegexValidator('^\\+\\d+$')],
+ ),
+ ),
+ (
+ 'personal_email',
+ models.EmailField(
+ help_text='if you provide a personal email address, notifications of new documents will also be sent to this address.',
+ max_length=75,
+ verbose_name='personal email address',
+ blank=True,
+ ),
+ ),
+ (
+ 'accept_notifications',
+ models.BooleanField(
+ default=True,
+ help_text='If unchecked you will not received notifications anymore, by email or SMS.',
+ verbose_name='Accept to be notified',
+ ),
+ ),
('user', models.OneToOneField(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)),
],
- options={
- },
+ options={},
bases=(models.Model,),
),
migrations.CreateModel(
name='Document',
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ (
+ 'id',
+ models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+ ),
('real_sender', models.CharField(max_length=64, verbose_name='Real sender', blank=True)),
- ('date', models.DateTimeField(default=django.utils.timezone.now, verbose_name="Date d'envoi")),
+ (
+ 'date',
+ models.DateTimeField(default=django.utils.timezone.now, verbose_name="Date d'envoi"),
+ ),
('comment', models.TextField(verbose_name='Comments', blank=True)),
('_timestamp', models.TextField(blank=True)),
- ('private', models.BooleanField(default=False, help_text='delegates cannot see this document', verbose_name='Private')),
+ (
+ 'private',
+ models.BooleanField(
+ default=False, help_text='delegates cannot see this document', verbose_name='Private'
+ ),
+ ),
],
options={
'base_manager_name': 'objects',
@@ -125,40 +200,76 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='DocumentForwarded',
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ (
+ 'id',
+ models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+ ),
('date', models.DateTimeField(auto_now_add=True)),
('automatic', models.BooleanField(default=False)),
- ('from_document', models.ForeignKey(related_name='document_forwarded_to', to='docbow.Document', on_delete=models.CASCADE)),
- ('to_document', models.ForeignKey(related_name='document_forwarded_from', to='docbow.Document', on_delete=models.CASCADE)),
+ (
+ 'from_document',
+ models.ForeignKey(
+ related_name='document_forwarded_to', to='docbow.Document', on_delete=models.CASCADE
+ ),
+ ),
+ (
+ 'to_document',
+ models.ForeignKey(
+ related_name='document_forwarded_from', to='docbow.Document', on_delete=models.CASCADE
+ ),
+ ),
],
- options={
- },
+ options={},
bases=(models.Model,),
),
migrations.CreateModel(
name='FileType',
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ (
+ 'id',
+ models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+ ),
('name', models.CharField(unique=True, max_length=128)),
('is_active', models.BooleanField(default=True, verbose_name='is active')),
],
- options={
- 'ordering': ['name'],
- 'verbose_name': 'File type',
- 'verbose_name_plural': 'File types',
- },
+ options={'ordering': ['name'], 'verbose_name': 'File type', 'verbose_name_plural': 'File types',},
bases=(docbow_project.docbow.models.NameNaturalKey, models.Model),
),
migrations.CreateModel(
name='FileTypeAttachedFileKind',
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ (
+ 'id',
+ models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+ ),
('name', models.CharField(max_length=128, verbose_name='name')),
- ('mime_types', models.TextField(help_text='mime types separated by spaces, wildcards are allowed', verbose_name='mime types', blank=True)),
- ('cardinality', models.PositiveSmallIntegerField(default=0, help_text='zero is a special value setting no limitation', verbose_name='cardinality')),
- ('minimum', models.PositiveSmallIntegerField(default=0, verbose_name='minimum number of files')),
+ (
+ 'mime_types',
+ models.TextField(
+ help_text='mime types separated by spaces, wildcards are allowed',
+ verbose_name='mime types',
+ blank=True,
+ ),
+ ),
+ (
+ 'cardinality',
+ models.PositiveSmallIntegerField(
+ default=0,
+ help_text='zero is a special value setting no limitation',
+ verbose_name='cardinality',
+ ),
+ ),
+ (
+ 'minimum',
+ models.PositiveSmallIntegerField(default=0, verbose_name='minimum number of files'),
+ ),
('position', models.PositiveSmallIntegerField(verbose_name='position')),
- ('file_type', models.ForeignKey(verbose_name='document type', to='docbow.FileType', on_delete=models.CASCADE)),
+ (
+ 'file_type',
+ models.ForeignKey(
+ verbose_name='document type', to='docbow.FileType', on_delete=models.CASCADE
+ ),
+ ),
],
options={
'ordering': ('file_type', 'position', 'name'),
@@ -170,27 +281,61 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='Mailbox',
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ (
+ 'id',
+ models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+ ),
('outbox', models.BooleanField(default=False, db_index=True, verbose_name='Outbox message')),
('date', models.DateTimeField(auto_now_add=True)),
- ('document', models.ForeignKey(related_name='mailboxes', verbose_name='Document', to='docbow.Document', on_delete=models.CASCADE)),
- ('owner', models.ForeignKey(related_name='documents', verbose_name='Mailbox owner', to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)),
+ (
+ 'document',
+ models.ForeignKey(
+ related_name='mailboxes',
+ verbose_name='Document',
+ to='docbow.Document',
+ on_delete=models.CASCADE,
+ ),
+ ),
+ (
+ 'owner',
+ models.ForeignKey(
+ related_name='documents',
+ verbose_name='Mailbox owner',
+ to=settings.AUTH_USER_MODEL,
+ on_delete=models.CASCADE,
+ ),
+ ),
],
- options={
- 'ordering': ['-date'],
- 'verbose_name': 'Mailbox',
- 'verbose_name_plural': 'Mailboxes',
- },
+ options={'ordering': ['-date'], 'verbose_name': 'Mailbox', 'verbose_name_plural': 'Mailboxes',},
bases=(models.Model,),
),
migrations.CreateModel(
name='MailingList',
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ (
+ 'id',
+ models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+ ),
('name', models.CharField(max_length=400, verbose_name='Name')),
('is_active', models.BooleanField(default=True, verbose_name='is active')),
- ('mailing_list_members', models.ManyToManyField(related_name='members_lists', verbose_name='Mailing lists members', to='docbow.MailingList', blank=True)),
- ('members', models.ManyToManyField(related_name='mailing_lists', verbose_name='Members', to=settings.AUTH_USER_MODEL, blank=True)),
+ (
+ 'mailing_list_members',
+ models.ManyToManyField(
+ related_name='members_lists',
+ verbose_name='Mailing lists members',
+ to='docbow.MailingList',
+ blank=True,
+ ),
+ ),
+ (
+ 'members',
+ models.ManyToManyField(
+ related_name='mailing_lists',
+ verbose_name='Members',
+ to=settings.AUTH_USER_MODEL,
+ blank=True,
+ ),
+ ),
],
options={
'ordering': ['name'],
@@ -202,28 +347,50 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='Notification',
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ (
+ 'id',
+ models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+ ),
('create_dt', models.DateTimeField(auto_now_add=True)),
('kind', models.CharField(default='new-document', max_length=32)),
('done', models.BooleanField(default=False)),
('failure', models.TextField(null=True, blank=True)),
('ctx', picklefield.fields.PickledObjectField(null=True, editable=False, blank=True)),
- ('document', models.ForeignKey(blank=True, to='docbow.Document', null=True, on_delete=models.CASCADE)),
- ('user', models.ForeignKey(blank=True, to=settings.AUTH_USER_MODEL, null=True, on_delete=models.CASCADE)),
+ (
+ 'document',
+ models.ForeignKey(blank=True, to='docbow.Document', null=True, on_delete=models.CASCADE),
+ ),
+ (
+ 'user',
+ models.ForeignKey(
+ blank=True, to=settings.AUTH_USER_MODEL, null=True, on_delete=models.CASCADE
+ ),
+ ),
],
- options={
- 'ordering': ('-id',),
- },
+ options={'ordering': ('-id',),},
bases=(models.Model,),
),
migrations.CreateModel(
name='NotificationPreference',
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ (
+ 'id',
+ models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+ ),
('kind', models.CharField(max_length=8, verbose_name='kind')),
('value', models.BooleanField(default=True, verbose_name='value')),
- ('filetype', models.ForeignKey(verbose_name='file type', to='docbow.FileType', on_delete=models.CASCADE)),
- ('user', models.ForeignKey(verbose_name='user', to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)),
+ (
+ 'filetype',
+ models.ForeignKey(
+ verbose_name='file type', to='docbow.FileType', on_delete=models.CASCADE
+ ),
+ ),
+ (
+ 'user',
+ models.ForeignKey(
+ verbose_name='user', to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE
+ ),
+ ),
],
options={
'ordering': ('user__last_name', 'user__first_name', 'kind'),
@@ -235,7 +402,10 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='SeenDocument',
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ (
+ 'id',
+ models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+ ),
('document', models.ForeignKey(to='docbow.Document', on_delete=models.CASCADE)),
('user', models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)),
],
@@ -249,10 +419,33 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='SendingLimitation',
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('filetypes', models.ManyToManyField(related_name='filetype_limitation', verbose_name='Limitation des types de fichier', to='docbow.FileType', blank=True)),
- ('lists', models.ManyToManyField(related_name='lists_limitation', verbose_name='Limitation des destinataires', to='docbow.MailingList')),
- ('mailing_list', models.OneToOneField(verbose_name='Mailing list', to='docbow.MailingList', on_delete=models.CASCADE)),
+ (
+ 'id',
+ models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+ ),
+ (
+ 'filetypes',
+ models.ManyToManyField(
+ related_name='filetype_limitation',
+ verbose_name='Limitation des types de fichier',
+ to='docbow.FileType',
+ blank=True,
+ ),
+ ),
+ (
+ 'lists',
+ models.ManyToManyField(
+ related_name='lists_limitation',
+ verbose_name='Limitation des destinataires',
+ to='docbow.MailingList',
+ ),
+ ),
+ (
+ 'mailing_list',
+ models.OneToOneField(
+ verbose_name='Mailing list', to='docbow.MailingList', on_delete=models.CASCADE
+ ),
+ ),
],
options={
'verbose_name': 'Limitation par liste de destinataires',
@@ -261,36 +454,56 @@ class Migration(migrations.Migration):
bases=(models.Model,),
),
migrations.AlterUniqueTogether(
- name='filetypeattachedfilekind',
- unique_together=set([('name', 'file_type')]),
+ name='filetypeattachedfilekind', unique_together=set([('name', 'file_type')]),
),
migrations.AddField(
model_name='document',
name='filetype',
- field=models.ForeignKey(verbose_name='Document type', to='docbow.FileType', on_delete=models.CASCADE),
+ field=models.ForeignKey(
+ verbose_name='Document type', to='docbow.FileType', on_delete=models.CASCADE
+ ),
preserve_default=True,
),
migrations.AddField(
model_name='document',
name='reply_to',
- field=models.ForeignKey(related_name='replies', verbose_name='Reply to', blank=True, to='docbow.Document', null=True, on_delete=models.CASCADE),
+ field=models.ForeignKey(
+ related_name='replies',
+ verbose_name='Reply to',
+ blank=True,
+ to='docbow.Document',
+ null=True,
+ on_delete=models.CASCADE,
+ ),
preserve_default=True,
),
migrations.AddField(
model_name='document',
name='sender',
- field=models.ForeignKey(related_name='documents_sent', verbose_name='Sender', to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE),
+ field=models.ForeignKey(
+ related_name='documents_sent',
+ verbose_name='Sender',
+ to=settings.AUTH_USER_MODEL,
+ on_delete=models.CASCADE,
+ ),
preserve_default=True,
),
migrations.AddField(
model_name='document',
name='to_list',
- field=models.ManyToManyField(to='docbow.MailingList', verbose_name='Groups to send to', blank=True),
+ field=models.ManyToManyField(
+ to='docbow.MailingList', verbose_name='Groups to send to', blank=True
+ ),
),
migrations.AddField(
model_name='document',
name='to_user',
- field=models.ManyToManyField(related_name='directly_received_documents', verbose_name='Users to send to', to=settings.AUTH_USER_MODEL, blank=True),
+ field=models.ManyToManyField(
+ related_name='directly_received_documents',
+ verbose_name='Users to send to',
+ to=settings.AUTH_USER_MODEL,
+ blank=True,
+ ),
),
migrations.AddField(
model_name='deletedmailbox',
@@ -310,83 +523,91 @@ class Migration(migrations.Migration):
field=models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE),
preserve_default=True,
),
- migrations.AlterUniqueTogether(
- name='delegation',
- unique_together=set([('by', 'to')]),
- ),
+ migrations.AlterUniqueTogether(name='delegation', unique_together=set([('by', 'to')]),),
migrations.AddField(
model_name='automaticforwarding',
name='filetypes',
- field=models.ManyToManyField(related_name='forwarding_rules', verbose_name='filetype', to='docbow.FileType'),
+ field=models.ManyToManyField(
+ related_name='forwarding_rules', verbose_name='filetype', to='docbow.FileType'
+ ),
preserve_default=True,
),
migrations.AddField(
model_name='automaticforwarding',
name='forward_to_list',
- field=models.ManyToManyField(related_name='as_recipient_forwarding_rules', verbose_name='Groups to forward to', to='docbow.MailingList', blank=True)
+ field=models.ManyToManyField(
+ related_name='as_recipient_forwarding_rules',
+ verbose_name='Groups to forward to',
+ to='docbow.MailingList',
+ blank=True,
+ ),
),
migrations.AddField(
model_name='automaticforwarding',
name='forward_to_user',
- field=models.ManyToManyField(related_name='as_recipient_forwarding_rules', verbose_name='Users to forward to', to=settings.AUTH_USER_MODEL, blank=True),
+ field=models.ManyToManyField(
+ related_name='as_recipient_forwarding_rules',
+ verbose_name='Users to forward to',
+ to=settings.AUTH_USER_MODEL,
+ blank=True,
+ ),
),
migrations.AddField(
model_name='automaticforwarding',
name='originaly_to_user',
- field=models.ManyToManyField(related_name='as_original_recipient_forwarding_rules', to=settings.AUTH_USER_MODEL, blank=True, help_text='At least one recipient must match for the rule to apply.', verbose_name='Original recipients'),
+ field=models.ManyToManyField(
+ related_name='as_original_recipient_forwarding_rules',
+ to=settings.AUTH_USER_MODEL,
+ blank=True,
+ help_text='At least one recipient must match for the rule to apply.',
+ verbose_name='Original recipients',
+ ),
),
migrations.AddField(
model_name='attachedfile',
name='document',
- field=models.ForeignKey(related_name='attached_files', verbose_name='Attached to', to='docbow.Document', on_delete=models.CASCADE),
+ field=models.ForeignKey(
+ related_name='attached_files',
+ verbose_name='Attached to',
+ to='docbow.Document',
+ on_delete=models.CASCADE,
+ ),
preserve_default=True,
),
migrations.AddField(
model_name='attachedfile',
name='kind',
- field=models.ForeignKey(verbose_name='attached file kind', blank=True, to='docbow.FileTypeAttachedFileKind', null=True, on_delete=models.CASCADE),
+ field=models.ForeignKey(
+ verbose_name='attached file kind',
+ blank=True,
+ to='docbow.FileTypeAttachedFileKind',
+ null=True,
+ on_delete=models.CASCADE,
+ ),
preserve_default=True,
),
migrations.CreateModel(
name='DocbowGroup',
- fields=[
- ],
- options={
- 'verbose_name': 'Docbow admin group',
- 'proxy': True,
- },
+ fields=[],
+ options={'verbose_name': 'Docbow admin group', 'proxy': True,},
bases=('auth.group',),
),
migrations.CreateModel(
name='DocbowUser',
- fields=[
- ],
- options={
- 'verbose_name': 'Docbow admin user',
- 'proxy': True,
- },
+ fields=[],
+ options={'verbose_name': 'Docbow admin user', 'proxy': True,},
bases=('auth.user',),
),
migrations.CreateModel(
name='Inbox',
- fields=[
- ],
- options={
- 'verbose_name': 'Inbox',
- 'proxy': True,
- 'verbose_name_plural': 'Inboxes',
- },
+ fields=[],
+ options={'verbose_name': 'Inbox', 'proxy': True, 'verbose_name_plural': 'Inboxes',},
bases=('docbow.mailbox',),
),
migrations.CreateModel(
name='Outbox',
- fields=[
- ],
- options={
- 'verbose_name': 'Outbox',
- 'proxy': True,
- 'verbose_name_plural': 'Outboxes',
- },
+ fields=[],
+ options={'verbose_name': 'Outbox', 'proxy': True, 'verbose_name_plural': 'Outboxes',},
bases=('docbow.mailbox',),
),
]
diff --git a/docbow_project/docbow/migrations/0002_auto_20190711_1812.py b/docbow_project/docbow/migrations/0002_auto_20190711_1812.py
index 8fa84bd..320ceb1 100644
--- a/docbow_project/docbow/migrations/0002_auto_20190711_1812.py
+++ b/docbow_project/docbow/migrations/0002_auto_20190711_1812.py
@@ -12,7 +12,5 @@ class Migration(migrations.Migration):
]
operations = [
- migrations.DeleteModel(
- name='DeletedMailbox',
- ),
+ migrations.DeleteModel(name='DeletedMailbox',),
]
diff --git a/docbow_project/docbow/migrations/0003_auto_20200319_1129.py b/docbow_project/docbow/migrations/0003_auto_20200319_1129.py
index aa7231b..f92867e 100644
--- a/docbow_project/docbow/migrations/0003_auto_20200319_1129.py
+++ b/docbow_project/docbow/migrations/0003_auto_20200319_1129.py
@@ -14,6 +14,11 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name='docbowprofile',
name='personal_email',
- field=models.EmailField(help_text='if you provide a personal email address, notifications of new documents will also be sent to this address.', max_length=254, verbose_name='personal email address', blank=True),
+ field=models.EmailField(
+ help_text='if you provide a personal email address, notifications of new documents will also be sent to this address.',
+ max_length=254,
+ verbose_name='personal email address',
+ blank=True,
+ ),
),
]
diff --git a/docbow_project/docbow/migrations/0005_soft_delete.py b/docbow_project/docbow/migrations/0005_soft_delete.py
index 8a50387..c4f4f07 100644
--- a/docbow_project/docbow/migrations/0005_soft_delete.py
+++ b/docbow_project/docbow/migrations/0005_soft_delete.py
@@ -13,13 +13,9 @@ class Migration(migrations.Migration):
operations = [
migrations.AddField(
- model_name='deleteddocument',
- name='soft_delete',
- field=models.BooleanField(default=False),
+ model_name='deleteddocument', name='soft_delete', field=models.BooleanField(default=False),
),
migrations.AddField(
- model_name='deleteddocument',
- name='soft_delete_date',
- field=models.DateTimeField(null=True),
+ model_name='deleteddocument', name='soft_delete_date', field=models.DateTimeField(null=True),
),
]
diff --git a/docbow_project/docbow/models.py b/docbow_project/docbow/models.py
index ccee52a..09ced73 100644
--- a/docbow_project/docbow/models.py
+++ b/docbow_project/docbow/models.py
@@ -7,9 +7,22 @@ import re
from collections import defaultdict
import time
-from django.db.models import (Model, ForeignKey, DateTimeField, CharField,
- FileField, ManyToManyField, TextField, Manager, BooleanField,
- OneToOneField, Q, EmailField, PositiveSmallIntegerField, CASCADE)
+from django.db.models import (
+ Model,
+ ForeignKey,
+ DateTimeField,
+ CharField,
+ FileField,
+ ManyToManyField,
+ TextField,
+ Manager,
+ BooleanField,
+ OneToOneField,
+ Q,
+ EmailField,
+ PositiveSmallIntegerField,
+ CASCADE,
+)
from django.contrib.auth.models import User, Group
from django.conf import settings
from django.template.defaultfilters import slugify
@@ -33,19 +46,20 @@ DOCBOW_APP = _('Docbow_App')
DOCBOW_APP2 = _('Docbow_app')
# fixup User ordering
-User._meta.ordering = [ 'username' ]
+User._meta.ordering = ['username']
def ellipsize(text, length=50):
text = html.unescape(strip_tags(text))
if len(text) < length:
return text
- return text[:(length-10)] + '...'
+ return text[: (length - 10)] + '...'
class GetByNameManager(Manager):
'''Manager providing a get_by_natural_key() method to retrieve object by
their name. The name field MUST be unique.'''
+
def get_by_natural_key(self, name):
return self.get(name=name)
@@ -53,6 +67,7 @@ class GetByNameManager(Manager):
class ContentManager(Manager):
'''Manager providing a get_by_natural_key() method to retrieve object by
their description. The description field MUST be unique.'''
+
def get_by_natural_key(self, description):
return self.get(description=description)
@@ -60,6 +75,7 @@ class ContentManager(Manager):
class NameNaturalKey(object):
'''Model mixin to export the name of a model as a natural key. The name
field MUST be unique.'''
+
def natural_key(self):
return (self.name,)
@@ -69,6 +85,7 @@ class FileType(NameNaturalKey, Model):
'''
A type of file that can be sent inside the application.
'''
+
objects = GetByNameManager()
name = CharField(max_length=128, unique=True)
@@ -90,22 +107,25 @@ class FileTypeAttachedFileKindManager(Manager):
@python_2_unicode_compatible
class FileTypeAttachedFileKind(Model):
- MIME_TYPES_RE = re.compile(r'^\s*(?:(?:text|image|audio|application|video)'
- r'/(?:\*|[a-z-]+)(?:\s+(?:text|image|audio|application|video)'
- r'/(?:\*|[a-z-.]+))*\s*)?$')
+ MIME_TYPES_RE = re.compile(
+ r'^\s*(?:(?:text|image|audio|application|video)'
+ r'/(?:\*|[a-z-]+)(?:\s+(?:text|image|audio|application|video)'
+ r'/(?:\*|[a-z-.]+))*\s*)?$'
+ )
objects = FileTypeAttachedFileKindManager()
name = CharField(max_length=128, verbose_name=_('name'))
file_type = ForeignKey('FileType', verbose_name=_('document type'), on_delete=CASCADE)
- mime_types = TextField(verbose_name=_('mime types'),
- help_text=('mime types separated by spaces, wildcards are allowed'),
- blank=True)
- cardinality = PositiveSmallIntegerField(default=0,
- verbose_name=_('cardinality'),
- help_text=_('zero is a special value setting no limitation'))
- minimum = PositiveSmallIntegerField(default=0,
- verbose_name=_('minimum number of files'))
+ mime_types = TextField(
+ verbose_name=_('mime types'),
+ help_text=('mime types separated by spaces, wildcards are allowed'),
+ blank=True,
+ )
+ cardinality = PositiveSmallIntegerField(
+ default=0, verbose_name=_('cardinality'), help_text=_('zero is a special value setting no limitation')
+ )
+ minimum = PositiveSmallIntegerField(default=0, verbose_name=_('minimum number of files'))
position = PositiveSmallIntegerField(verbose_name=_('position'))
class Meta:
@@ -116,7 +136,9 @@ class FileTypeAttachedFileKind(Model):
def clean(self):
if self.cardinality != 0 and not self.minimum <= self.cardinality:
- raise ValidationError(_('minimum must be inferior to maximum number of files if maximum is not zero'))
+ raise ValidationError(
+ _('minimum must be inferior to maximum number of files if maximum is not zero')
+ )
if self.mime_types:
if not self.MIME_TYPES_RE.match(self.mime_types):
raise ValidationError(_('invalid mime types list'))
@@ -125,8 +147,7 @@ class FileTypeAttachedFileKind(Model):
return list(filter(None, re.split(r'\s+', self.mime_types.strip())))
def match_file(self, file_like):
- return file_match_mime_types(
- file_like, self.get_mime_types(), app_settings.MIME_BUFFER_SIZE)
+ return file_match_mime_types(file_like, self.get_mime_types(), app_settings.MIME_BUFFER_SIZE)
def natural_key(self):
return (self.name, self.file_type.name)
@@ -138,6 +159,7 @@ class FileTypeAttachedFileKind(Model):
@python_2_unicode_compatible
class Content(Model):
'''Predefined content type'''
+
objects = ContentManager()
description = CharField(max_length=128, unique=True)
@@ -186,12 +208,11 @@ FORWARD_PERMISSION = 'FORWARD_DOCUMENT'
class DocumentManager(Manager):
-
def get_query_set(self):
'''Prefetch as much as possible.'''
- return super(DocumentManager, self).get_query_set() \
- .select_related() \
- .prefetch_related('attached_files')
+ return (
+ super(DocumentManager, self).get_query_set().select_related().prefetch_related('attached_files')
+ )
@python_2_unicode_compatible
@@ -206,45 +227,44 @@ class Document(Model):
ordering = ['-date']
verbose_name = _('Document')
verbose_name_plural = _('Documents')
- permissions = (
- (FORWARD_PERMISSION, _("Can forward documents")),
- )
+ permissions = ((FORWARD_PERMISSION, _("Can forward documents")),)
base_manager_name = 'objects'
-
- sender = ForeignKey(User, verbose_name=_('Sender'), on_delete=CASCADE,
- related_name='documents_sent')
+ sender = ForeignKey(User, verbose_name=_('Sender'), on_delete=CASCADE, related_name='documents_sent')
real_sender = CharField(max_length=64, blank=True, verbose_name=_('Real sender'))
- date = DateTimeField(default=now,
- verbose_name=_("Date d'envoi"))
- to_user = ManyToManyField(User, related_name='directly_received_documents',
- blank=True, verbose_name=_('Users to send to'))
- to_list = ManyToManyField('MailingList', blank=True,
- verbose_name=_('Groups to send to'))
- filetype = ForeignKey(FileType, verbose_name=_('Document type'), on_delete=CASCADE,
- limit_choices_to={'is_active': True})
+ date = DateTimeField(default=now, verbose_name=_("Date d'envoi"))
+ to_user = ManyToManyField(
+ User, related_name='directly_received_documents', blank=True, verbose_name=_('Users to send to')
+ )
+ to_list = ManyToManyField('MailingList', blank=True, verbose_name=_('Groups to send to'))
+ filetype = ForeignKey(
+ FileType, verbose_name=_('Document type'), on_delete=CASCADE, limit_choices_to={'is_active': True}
+ )
comment = TextField(blank=True, verbose_name=_('Comments'))
_timestamp = TextField(blank=True)
- reply_to = ForeignKey('self', verbose_name=_('Reply to'), on_delete=CASCADE,
- blank=True, null=True, related_name='replies')
- private = BooleanField(default=False, verbose_name=_('Private'),
- help_text=_('delegates cannot see this document'))
+ reply_to = ForeignKey(
+ 'self', verbose_name=_('Reply to'), on_delete=CASCADE, blank=True, null=True, related_name='replies'
+ )
+ private = BooleanField(
+ default=False, verbose_name=_('Private'), help_text=_('delegates cannot see this document')
+ )
def __str__(self):
'''Return a displayable representation of the document sending.'''
ctx = {
- 'id': self.id,
- 'date': self.date.date().isoformat(),
- 'filetype': self.filetype,
- 'comment': self.comment,
- 'sender': username(self.sender),
- }
+ 'id': self.id,
+ 'date': self.date.date().isoformat(),
+ 'filetype': self.filetype,
+ 'comment': self.comment,
+ 'sender': username(self.sender),
+ }
return _('document {id} sent on {date} of type {filetype} about {comment} by {sender}').format(**ctx)
def filenames(self):
'''Returns a display string for the list of attached files'''
- files = [ attached_file for attached_file in self.attached_files.all() ]
+ files = [attached_file for attached_file in self.attached_files.all()]
return ', '.join([f.filename() for f in files])
+
filenames.short_description = _('Attached files')
def filename_links(self):
@@ -263,6 +283,7 @@ class Document(Model):
links[-1] = kind.name + ' : ' + links[-1]
last_kind_name = kind.name
return mark_safe(', '.join(links))
+
filename_links.short_description = _('Attached files')
def user_human_to(self):
@@ -275,14 +296,14 @@ class Document(Model):
def human_to(self):
'''Return a sorted list of display names for all recipients.'''
- return sorted(list(map(username, self.to_user.all())) + \
- list(map(force_text, self.to_list.all())))
+ return sorted(list(map(username, self.to_user.all())) + list(map(force_text, self.to_list.all())))
def recipients(self):
'''Return a comma separated sorted list of display names for all
recipients.
'''
return ', '.join(self.human_to())
+
recipients.short_description = _('Recipients')
def to(self):
@@ -315,8 +336,12 @@ class Document(Model):
self._timestamp = time.time()
self.date = dt.datetime.fromtimestamp(self._timestamp, utc)
self.save()
- django_journal.record('timestamp', 'timestamped document {document} result is {timestamp}',
- document=self, timestamp=self._timestamp)
+ django_journal.record(
+ 'timestamp',
+ 'timestamped document {document} result is {timestamp}',
+ document=self,
+ timestamp=self._timestamp,
+ )
return self._timestamp
def post(self, forward=True):
@@ -329,30 +354,49 @@ class Document(Model):
self.timestamp(to=to)
# Record recipient lists
for mailing_list in self.to_list.all():
- django_journal.record('delivery', 'deliver document {document} to members of list {mailing_list}',
- document=self, mailing_list=mailing_list)
+ django_journal.record(
+ 'delivery',
+ 'deliver document {document} to members of list {mailing_list}',
+ document=self,
+ mailing_list=mailing_list,
+ )
for user in to:
Mailbox.objects.get_or_create(owner=user, document=self)
- if '--direct--' not in to_with_origins[user] or \
- len(to_with_origins[user]) > 1:
+ if '--direct--' not in to_with_origins[user] or len(to_with_origins[user]) > 1:
lists = u', '.join(m.name for m in to_with_origins[user] if m != '--direct--')
if '--direct--' in to_with_origins[user]:
- django_journal.record('delivery', 'deliver document '
- '{document} in mailbox of user {recipient} '
- 'member of {lists} and as a direct recipient',
- document=self, recipient=user, lists=lists)
+ django_journal.record(
+ 'delivery',
+ 'deliver document '
+ '{document} in mailbox of user {recipient} '
+ 'member of {lists} and as a direct recipient',
+ document=self,
+ recipient=user,
+ lists=lists,
+ )
else:
- django_journal.record('delivery', 'deliver document '
- '{document} in mailbox of user {recipient} '
- 'member of {lists}',
- document=self, recipient=user, lists=lists)
+ django_journal.record(
+ 'delivery',
+ 'deliver document ' '{document} in mailbox of user {recipient} ' 'member of {lists}',
+ document=self,
+ recipient=user,
+ lists=lists,
+ )
else:
- django_journal.record('delivery', 'deliver document {document} in mailbox of user {recipient} as a direct recipient',
- document=self, recipient=user)
+ django_journal.record(
+ 'delivery',
+ 'deliver document {document} in mailbox of user {recipient} as a direct recipient',
+ document=self,
+ recipient=user,
+ )
# Deliver to ouput mailbox of the sender
Mailbox.objects.get_or_create(owner=self.sender, outbox=True, document=self)
- django_journal.record('delivery', 'deliver document {document} in output mailbox of user {recipient}',
- document=self, recipient=self.sender)
+ django_journal.record(
+ 'delivery',
+ 'deliver document {document} in output mailbox of user {recipient}',
+ document=self,
+ recipient=self.sender,
+ )
# Push notifications
Notification.objects.notify(document=self, users=to)
if forward:
@@ -368,25 +412,27 @@ class Document(Model):
automatic - whether this forwarding is the result of an
automatic treatment
'''
- document = Document.objects.create(sender=new_sender,
- filetype=self.filetype,
- comment=self.comment)
+ document = Document.objects.create(sender=new_sender, filetype=self.filetype, comment=self.comment)
document.to_user.set(users)
document.to_list.set(lists)
- attached_files = [ AttachedFile(name=attached_file.name,
- content=attached_file.content,
- document=document) for attached_file in self.attached_files.all()]
+ attached_files = [
+ AttachedFile(name=attached_file.name, content=attached_file.content, document=document)
+ for attached_file in self.attached_files.all()
+ ]
AttachedFile.objects.bulk_create(attached_files)
recipients_count = document.post(forward=False)
- return recipients_count, DocumentForwarded.objects.create(from_document=self,
- to_document=document, automatic=automatic)
+ return (
+ recipients_count,
+ DocumentForwarded.objects.create(from_document=self, to_document=document, automatic=automatic),
+ )
def sender_display(self):
return username(self.sender)
def url(self):
- return urlparse.urljoin(app_settings.BASE_URL,
- reverse('inbox-message', kwargs=dict(mailbox_id=self.id)))
+ return urlparse.urljoin(
+ app_settings.BASE_URL, reverse('inbox-message', kwargs=dict(mailbox_id=self.id))
+ )
def has_zip_download(self):
return self.attached_files.count() > 1 and settings.ZIP_DOWNLOAD
@@ -394,6 +440,7 @@ class Document(Model):
class SeenDocument(Model):
'''Mark a document as seen'''
+
document = ForeignKey('Document', on_delete=CASCADE)
user = ForeignKey('auth.User', on_delete=CASCADE)
@@ -402,8 +449,10 @@ class SeenDocument(Model):
verbose_name_plural = _('seen documents')
ordering = ('-document',)
+
class DeletedDocument(Model):
'''Mark a document as deleted'''
+
document = ForeignKey('Document', on_delete=CASCADE)
user = ForeignKey('auth.User', on_delete=CASCADE)
soft_delete = BooleanField(default=False)
@@ -421,6 +470,7 @@ class DocumentForwarded(Model):
First use will be to mark message as having been forwarded.
'''
+
from_document = ForeignKey(Document, related_name='document_forwarded_to', on_delete=CASCADE)
to_document = ForeignKey(Document, related_name='document_forwarded_from', on_delete=CASCADE)
date = DateTimeField(auto_now_add=True)
@@ -429,14 +479,12 @@ class DocumentForwarded(Model):
def __str__(self):
if self.automatic:
return _(u'forwarded document {from_document} as {to_document} on {date} automatically').format(
- from_document=self.from_document,
- to_document=self.to_document,
- date=self.date)
+ from_document=self.from_document, to_document=self.to_document, date=self.date
+ )
else:
return _(u'forwarded document {from_document} as {to_document} on {date}').format(
- from_document=self.from_document,
- to_document=self.to_document,
- date=self.date)
+ from_document=self.from_document, to_document=self.to_document, date=self.date
+ )
def list_to_csv(l, mapping_func=None):
@@ -456,17 +504,29 @@ class AutomaticForwarding(Model):
Choice of sender and filetype to transfer mail automatically to a list
of recipients.
'''
- filetypes = ManyToManyField(FileType, related_name='forwarding_rules',
- verbose_name=_('filetype'),
- limit_choices_to={'is_active': True})
- originaly_to_user = ManyToManyField(User, related_name='as_original_recipient_forwarding_rules',
- blank=True, verbose_name=_('Original recipients'),
- help_text=_('At least one recipient must match for the rule to '
- 'apply.'))
- forward_to_user = ManyToManyField(User, related_name='as_recipient_forwarding_rules',
- blank=True, verbose_name=_('Users to forward to'))
- forward_to_list = ManyToManyField('MailingList', blank=True,
- verbose_name=_('Groups to forward to'), related_name='as_recipient_forwarding_rules')
+
+ filetypes = ManyToManyField(
+ FileType,
+ related_name='forwarding_rules',
+ verbose_name=_('filetype'),
+ limit_choices_to={'is_active': True},
+ )
+ originaly_to_user = ManyToManyField(
+ User,
+ related_name='as_original_recipient_forwarding_rules',
+ blank=True,
+ verbose_name=_('Original recipients'),
+ help_text=_('At least one recipient must match for the rule to ' 'apply.'),
+ )
+ forward_to_user = ManyToManyField(
+ User, related_name='as_recipient_forwarding_rules', blank=True, verbose_name=_('Users to forward to')
+ )
+ forward_to_list = ManyToManyField(
+ 'MailingList',
+ blank=True,
+ verbose_name=_('Groups to forward to'),
+ related_name='as_recipient_forwarding_rules',
+ )
class Meta:
verbose_name = _('Automatic forwarding rule')
@@ -475,10 +535,10 @@ class AutomaticForwarding(Model):
def __str__(self):
'''Return a display string for the forwarding rule.'''
ctx = {
- 'filetypes': list_to_csv(self.filetypes.all()),
- 'originaly_to_user': list_to_csv(map(username, self.originaly_to_user.all())),
- 'to': list_to_csv(map(username, self.forward_to_user.all())
- + list(self.forward_to_list.all())) }
+ 'filetypes': list_to_csv(self.filetypes.all()),
+ 'originaly_to_user': list_to_csv(map(username, self.originaly_to_user.all())),
+ 'to': list_to_csv(map(username, self.forward_to_user.all()) + list(self.forward_to_list.all())),
+ }
assert self.filetypes.all() or self.originaly_to_user.all()
if self.filetypes.all() and self.originaly_to_user.all():
tpl = _('Forward documents of type {filetypes} and to {originaly_to_user} automatically to {to}')
@@ -491,30 +551,44 @@ class AutomaticForwarding(Model):
@classmethod
def try_forwarding(self, document):
'''Try applying matching rules to the document'''
- for rule in self.objects.filter(Q(filetypes=document.filetype,
- originaly_to_user__in=document.to())|
- Q(filetypes=document.filetype, originaly_to_user__isnull=True)):
- recipients_count, document_forwarded = document.forward(document.sender,
- users=rule.forward_to_user.all(),
- lists=rule.forward_to_list.all(),
- automatic=True)
- django_journal.record('automatic-forward', 'document {document} '
- 'automatically forwarded to {recipients_count} new recipients '
- 'as document {new_document}', document=document_forwarded.from_document,
- new_document=document_forwarded.to_document,
- recipients_count=recipients_count,
- document_forwarded=document_forwarded)
+ for rule in self.objects.filter(
+ Q(filetypes=document.filetype, originaly_to_user__in=document.to())
+ | Q(filetypes=document.filetype, originaly_to_user__isnull=True)
+ ):
+ recipients_count, document_forwarded = document.forward(
+ document.sender,
+ users=rule.forward_to_user.all(),
+ lists=rule.forward_to_list.all(),
+ automatic=True,
+ )
+ django_journal.record(
+ 'automatic-forward',
+ 'document {document} '
+ 'automatically forwarded to {recipients_count} new recipients '
+ 'as document {new_document}',
+ document=document_forwarded.from_document,
+ new_document=document_forwarded.to_document,
+ recipients_count=recipients_count,
+ document_forwarded=document_forwarded,
+ )
@python_2_unicode_compatible
class AttachedFile(Model):
'''Uploaded file attached to a Document'''
+
name = CharField(max_length=300, verbose_name=_('Name'))
content = FileField(max_length=300, upload_to=generate_filename, verbose_name=_('File'))
- document = ForeignKey(Document, verbose_name=_('Attached to'), on_delete=CASCADE,
- related_name='attached_files')
- kind = ForeignKey('FileTypeAttachedFileKind', blank=True, null=True, on_delete=CASCADE,
- verbose_name=_('attached file kind'))
+ document = ForeignKey(
+ Document, verbose_name=_('Attached to'), on_delete=CASCADE, related_name='attached_files'
+ )
+ kind = ForeignKey(
+ 'FileTypeAttachedFileKind',
+ blank=True,
+ null=True,
+ on_delete=CASCADE,
+ verbose_name=_('attached file kind'),
+ )
def filename(self):
'''Extract the original filename from generated unique filename for
@@ -544,6 +618,7 @@ class AttachedFile(Model):
def __str__(self):
return self.name
+
def is_guest(user):
try:
return user.docbowprofile.is_guest
@@ -557,19 +632,26 @@ class Delegation(Model):
Delegate account, managable by user themselves.
'''
- by = ForeignKey(User, related_name='delegations_to', on_delete=CASCADE,
- verbose_name=pgettext_lazy('delegation from', "From"))
- to = ForeignKey(User, related_name='delegations_by', on_delete=CASCADE,
- verbose_name=pgettext_lazy('delegation to', "To"))
+ by = ForeignKey(
+ User,
+ related_name='delegations_to',
+ on_delete=CASCADE,
+ verbose_name=pgettext_lazy('delegation from', "From"),
+ )
+ to = ForeignKey(
+ User,
+ related_name='delegations_by',
+ on_delete=CASCADE,
+ verbose_name=pgettext_lazy('delegation to', "To"),
+ )
class Meta:
- ordering = [ 'by' ]
+ ordering = ['by']
verbose_name = _('Account delegation')
verbose_name_plural = _('Account delegations')
db_table = 'auth_delegation'
unique_together = (('by', 'to'),)
-
def __str__(self):
return u'delegation from {0}:{0.id} to {1}:{1.id}'.format(self.by, self.to)
@@ -590,7 +672,7 @@ class MailingListManager(GetByNameManager):
def are_member_of(self, users):
lists = set(MailingList.objects.filter(is_active=True).filter(members__in=users))
- while True: # accumulate lists until it grows no more
+ while True: # accumulate lists until it grows no more
old_count = len(lists)
lists |= set(MailingList.objects.filter(is_active=True).filter(mailing_list_members__in=lists))
if old_count == len(lists):
@@ -603,18 +685,16 @@ class MailingList(NameNaturalKey, Model):
'''A list of recipients.'''
name = CharField(max_length=400, verbose_name=_('Name'))
- members = ManyToManyField(User, verbose_name=_('Members'), blank=True,
- related_name='mailing_lists')
- mailing_list_members = ManyToManyField('MailingList',
- verbose_name=_('Mailing lists members'),
- blank=True, related_name='members_lists')
- is_active = BooleanField(verbose_name=_('is active'), blank=True,
- default=True)
+ members = ManyToManyField(User, verbose_name=_('Members'), blank=True, related_name='mailing_lists')
+ mailing_list_members = ManyToManyField(
+ 'MailingList', verbose_name=_('Mailing lists members'), blank=True, related_name='members_lists'
+ )
+ is_active = BooleanField(verbose_name=_('is active'), blank=True, default=True)
objects = MailingListManager()
class Meta:
- ordering = [ 'name' ]
+ ordering = ['name']
verbose_name = _('Mailing list')
verbose_name_plural = _('Mailing lists')
@@ -635,15 +715,14 @@ class MailingList(NameNaturalKey, Model):
'''Traverse this list and all its recursive sublist and accumulate
members and their origin.'''
if sublist_traversed is None:
- sublist_traversed = defaultdict(lambda:0)
+ sublist_traversed = defaultdict(lambda: 0)
sublist_traversed[self] += 1
- members = defaultdict(lambda:set())
+ members = defaultdict(lambda: set())
for member in self.members.filter(is_active=True):
members[member].add(self)
for sublist in self.mailing_list_members.all():
if sublist_traversed[sublist] < 3:
- sub_members = sublist.recursive_members_with_origin(
- sublist_traversed).items()
+ sub_members = sublist.recursive_members_with_origin(sublist_traversed).items()
for member, list_set in sub_members:
members[member] |= list_set
members[member].add(self)
@@ -656,24 +735,22 @@ class MailingList(NameNaturalKey, Model):
@python_2_unicode_compatible
class Mailbox(Model):
'''List of document received by a user'''
- owner = ForeignKey(User, verbose_name=_('Mailbox owner'), on_delete=CASCADE,
- related_name='documents')
- document = ForeignKey(Document, verbose_name=('Document'), on_delete=CASCADE,
- related_name='mailboxes')
- outbox = BooleanField(verbose_name=_('Outbox message'), blank=True,
- default=False, db_index=True)
+
+ owner = ForeignKey(User, verbose_name=_('Mailbox owner'), on_delete=CASCADE, related_name='documents')
+ document = ForeignKey(Document, verbose_name=('Document'), on_delete=CASCADE, related_name='mailboxes')
+ outbox = BooleanField(verbose_name=_('Outbox message'), blank=True, default=False, db_index=True)
date = DateTimeField(auto_now_add=True)
class Meta:
- ordering = [ '-date' ]
+ ordering = ['-date']
verbose_name = _('Mailbox')
verbose_name_plural = _('Mailboxes')
def __str__(self):
- return _(u'mailbox entry {id} of user {user}:{user.id} created on '
- u'{date} for {document}').format(id=self.id, user=self.owner,
- date=self.date,
- document=self.document)
+ return _(u'mailbox entry {id} of user {user}:{user.id} created on ' u'{date} for {document}').format(
+ id=self.id, user=self.owner, date=self.date, document=self.document
+ )
+
class DocbowUser(User):
class Meta:
@@ -705,14 +782,19 @@ class Outbox(Mailbox):
@python_2_unicode_compatible
class SendingLimitation(Model):
- mailing_list = OneToOneField(MailingList, unique=True, on_delete=CASCADE,
- verbose_name=MailingList._meta.verbose_name)
- filetypes = ManyToManyField(FileType, blank=True,
- related_name='filetype_limitation',
- verbose_name=_('Limitation des types de fichier'),
- limit_choices_to={'is_active': True})
- lists = ManyToManyField(MailingList, related_name='lists_limitation',
- verbose_name=_('Limitation des destinataires'))
+ mailing_list = OneToOneField(
+ MailingList, unique=True, on_delete=CASCADE, verbose_name=MailingList._meta.verbose_name
+ )
+ filetypes = ManyToManyField(
+ FileType,
+ blank=True,
+ related_name='filetype_limitation',
+ verbose_name=_('Limitation des types de fichier'),
+ limit_choices_to={'is_active': True},
+ )
+ lists = ManyToManyField(
+ MailingList, related_name='lists_limitation', verbose_name=_('Limitation des destinataires')
+ )
class Meta:
verbose_name = _('Limitation par liste de destinataires')
@@ -720,48 +802,57 @@ class SendingLimitation(Model):
verbose_name_plural = verbose_name
def __str__(self):
- return _(u'sending limitation for list {mailing_list} to filetypes'
- u'{filetypes} and lists {lists}').format(
- mailing_list=self.mailing_list,
- filetypes=list_to_csv(self.filetypes.all()),
- lists=list_to_csv(self.lists.all()))
+ return _(
+ u'sending limitation for list {mailing_list} to filetypes' u'{filetypes} and lists {lists}'
+ ).format(
+ mailing_list=self.mailing_list,
+ filetypes=list_to_csv(self.filetypes.all()),
+ lists=list_to_csv(self.lists.all()),
+ )
@python_2_unicode_compatible
class DocbowProfile(Model):
'''Hold extra user attributes'''
+
user = OneToOneField(User, unique=True, on_delete=CASCADE)
- is_guest = BooleanField(verbose_name=_('Guest user'), blank=True,
- default=False)
- mobile_phone = CharField(max_length=32, verbose_name=_('Mobile phone'),
- blank=True, validators=[validate_phone])
- personal_email = EmailField(_('personal email address'), blank=True,
- help_text=_('if you provide a personal email address, notifications '
- 'of new documents will also be sent to this address.'))
+ is_guest = BooleanField(verbose_name=_('Guest user'), blank=True, default=False)
+ mobile_phone = CharField(
+ max_length=32, verbose_name=_('Mobile phone'), blank=True, validators=[validate_phone]
+ )
+ personal_email = EmailField(
+ _('personal email address'),
+ blank=True,
+ help_text=_(
+ 'if you provide a personal email address, notifications '
+ 'of new documents will also be sent to this address.'
+ ),
+ )
accept_notifications = BooleanField(
- verbose_name=_('Accept to be notified'), blank=True, default=True,
- help_text=_("If unchecked you will not received notifications "
- "anymore, by email or SMS."))
+ verbose_name=_('Accept to be notified'),
+ blank=True,
+ default=True,
+ help_text=_("If unchecked you will not received notifications " "anymore, by email or SMS."),
+ )
external_id = CharField(max_length=256, verbose_name=_('External identifer'), blank=True)
def __str__(self):
- return _(u'docbow profile of {user}:{user.id} with mobile phone '
- u'{mobile_phone} and personal email {personal_email}').format(
- user=self.user,
- mobile_phone=self.mobile_phone,
- personal_email=self.personal_email)
+ return _(
+ u'docbow profile of {user}:{user.id} with mobile phone '
+ u'{mobile_phone} and personal email {personal_email}'
+ ).format(user=self.user, mobile_phone=self.mobile_phone, personal_email=self.personal_email)
class NotificationManager(Manager):
def notify(self, document=None, users=None, kind='new-document', ctx=None):
'''Build notifications in bulk'''
- users = set(users)
+ users = set(users)
if document and not document.private:
users |= set(User.objects.filter(delegations_by__by__in=users, is_active=True))
- users = User.objects.filter(pk__in=[u.pk for u in users]) \
- .exclude(docbowprofile__accept_notifications=False)
- notifications = [Notification(user=user, document=document, kind=kind, ctx=ctx)
- for user in users]
+ users = User.objects.filter(pk__in=[u.pk for u in users]).exclude(
+ docbowprofile__accept_notifications=False
+ )
+ notifications = [Notification(user=user, document=document, kind=kind, ctx=ctx) for user in users]
self.bulk_create(notifications)
@@ -778,6 +869,7 @@ class Notification(Model):
was successful if this is empty.
ctx - a pickled object
'''
+
objects = NotificationManager()
create_dt = DateTimeField(auto_now_add=True)
@@ -797,6 +889,7 @@ class Notification(Model):
class NotificationPreference(Model):
'''Store preferences of users toward notification methods'''
+
user = ForeignKey(User, verbose_name=_('user'), on_delete=CASCADE)
filetype = ForeignKey(FileType, verbose_name=_('file type'), on_delete=CASCADE)
kind = CharField(max_length=8, verbose_name=_('kind'))
@@ -807,15 +900,18 @@ class NotificationPreference(Model):
verbose_name = _('notification preference')
verbose_name_plural = _('notification preferences')
+
def guest_users():
return User.objects.filter(docbowprofile__is_guest=True).filter(is_active=True)
+
def non_guest_users():
return User.objects.exclude(docbowprofile__is_guest=True).filter(is_active=True)
import watson.search as watson
+
class DocumentAdapter(watson.SearchAdapter):
def gather_strings(self, obj):
yield obj.comment
diff --git a/docbow_project/docbow/notification.py b/docbow_project/docbow/notification.py
index 0fdde4b..cd28f27 100644
--- a/docbow_project/docbow/notification.py
+++ b/docbow_project/docbow/notification.py
@@ -13,6 +13,7 @@ from docbow_project.docbow import app_settings
logger = logging.getLogger(__name__)
+
class BaseNotifier(object):
def __init__(self):
# accumulate preferences of users first
@@ -46,6 +47,7 @@ class BaseNotifier(object):
def finish(self):
pass
+
class MailNotifier(BaseNotifier):
description = _('Email')
key = 'email'
@@ -79,17 +81,18 @@ class MailNotifier(BaseNotifier):
subject = subject.replace('\n', '').replace('\r', '')
body = self.generate_part(self.body_template, notification)
html_body = self.generate_part(self.html_body_template, notification)
- mail = EmailMultiAlternatives(to=list(to), subject=subject, body=body,
- headers=headers)
+ mail = EmailMultiAlternatives(to=list(to), subject=subject, body=body, headers=headers)
if html_body:
mail.attach_alternative(html_body, 'text/html')
mail.send(fail_silently=False)
- django_journal.record('mail-notify', 'mail notification {notification} '
- 'sent for document {document} to {to} of user {recipient}',
- notification=notification,
- recipient=notification.user,
- document=notification.document,
- to=','.join(to))
+ django_journal.record(
+ 'mail-notify',
+ 'mail notification {notification} ' 'sent for document {document} to {to} of user {recipient}',
+ notification=notification,
+ recipient=notification.user,
+ document=notification.document,
+ to=','.join(to),
+ )
class SMSNotifier(BaseNotifier):
@@ -97,6 +100,7 @@ class SMSNotifier(BaseNotifier):
- document
- settings
'''
+
description = _('SMS')
key = 'sms'
body_template = 'docbow/sms-notification_{kind}_body.txt'
@@ -114,8 +118,9 @@ class SMSNotifier(BaseNotifier):
return
if not profile.mobile_phone:
return
- self.mobile_phones.setdefault((notification.document, notification.kind), []) \
- .append((notification.user, profile.mobile_phone))
+ self.mobile_phones.setdefault((notification.document, notification.kind), []).append(
+ (notification.user, profile.mobile_phone)
+ )
@classmethod
def get_carrier(cls):
@@ -132,11 +137,14 @@ class SMSNotifier(BaseNotifier):
body = self.generate_part(self.body_template, notification)
sms_carrier = self.get_carrier()
for user, phone_number in value:
- django_journal.record('sms-notify',
- 'sms notification for document {document} to user '
- '{recipient} with phone number {phone_number}',
- document=document, recipient=user,
- phone_number=phone_number)
+ django_journal.record(
+ 'sms-notify',
+ 'sms notification for document {document} to user '
+ '{recipient} with phone number {phone_number}',
+ document=document,
+ recipient=user,
+ phone_number=phone_number,
+ )
sms_carrier.send_sms([v[1] for v in value], body)
except Exception as e:
exc = e
@@ -144,7 +152,6 @@ class SMSNotifier(BaseNotifier):
raise exc
-
def resolve_class(class_path):
module, cls_name = class_path.rsplit('.', 1)
module = importlib.import_module(module)
@@ -152,30 +159,33 @@ def resolve_class(class_path):
def get_notifiers():
- notification_classes = getattr(settings, 'DOCBOW_NOTIFIERS', [
- 'docbow_project.docbow.notification.MailNotifier' ])
+ notification_classes = getattr(
+ settings, 'DOCBOW_NOTIFIERS', ['docbow_project.docbow.notification.MailNotifier']
+ )
return [resolve_class(class_path)() for class_path in notification_classes]
def process_notifications():
notifiers = get_notifiers()
- for notification in models.Notification.objects.order_by('id') \
- .select_for_update().filter(done=False):
+ for notification in models.Notification.objects.order_by('id').select_for_update().filter(done=False):
for notifier in notifiers:
failures = []
if not notifier.skip(notification):
try:
notifier.process(notification)
except Exception as e:
- failures.append(u'Exception %r when handling with notifier %r'
- % (force_text(e), notifier.__class__))
- logger.exception('Exception when handling notification %r with notifier %r',
- notification, notifier)
- django_journal.error_record('error',
- 'notification {notification} failed for '
- 'notifier {notifier}',
- notification=notification,
- notifier=notifier.__class__)
+ failures.append(
+ u'Exception %r when handling with notifier %r' % (force_text(e), notifier.__class__)
+ )
+ logger.exception(
+ 'Exception when handling notification %r with notifier %r', notification, notifier
+ )
+ django_journal.error_record(
+ 'error',
+ 'notification {notification} failed for ' 'notifier {notifier}',
+ notification=notification,
+ notifier=notifier.__class__,
+ )
notification.done = True
if len(failures) > 0:
notification.failure = ','.join(failures)
@@ -184,9 +194,14 @@ def process_notifications():
try:
notifier.finish()
except Exception as e:
- logger.exception('Exception when finishing handling '
- 'notification %r with notifier %r', notification, notifier)
- django_journal.error_record('error', 'unable to finish sending '
- 'notification with notifier {notifier}, error: {error}',
- notifier=notifier.__class__,
- error=force_text(e))
+ logger.exception(
+ 'Exception when finishing handling ' 'notification %r with notifier %r',
+ notification,
+ notifier,
+ )
+ django_journal.error_record(
+ 'error',
+ 'unable to finish sending ' 'notification with notifier {notifier}, error: {error}',
+ notifier=notifier.__class__,
+ error=force_text(e),
+ )
diff --git a/docbow_project/docbow/ods.py b/docbow_project/docbow/ods.py
index 6b8b011..cf53060 100644
--- a/docbow_project/docbow/ods.py
+++ b/docbow_project/docbow/ods.py
@@ -64,17 +64,23 @@ class Workbook(object):
z = zipfile.ZipFile(output, 'w')
z.writestr('content.xml', self.get_data())
z.writestr('mimetype', 'application/vnd.oasis.opendocument.spreadsheet')
- z.writestr('META-INF/manifest.xml', '''
+ z.writestr(
+ 'META-INF/manifest.xml',
+ '''
-''')
- z.writestr('styles.xml', '''
+''',
+ )
+ z.writestr(
+ 'styles.xml',
+ '''
-''')
+''',
+ )
z.close()
@@ -93,9 +99,9 @@ class WorkSheet(object):
root = ET.Element('{%s}table' % TABLE_NS)
root.attrib['{%s}name' % TABLE_NS] = self.name
ET.SubElement(root, '{%s}table-column' % TABLE_NS)
- for i in range(0, max(self.cells.keys())+1):
+ for i in range(0, max(self.cells.keys()) + 1):
row = ET.SubElement(root, '{%s}table-row' % TABLE_NS)
- for j in range(0, max(self.cells.get(i).keys())+1):
+ for j in range(0, max(self.cells.get(i).keys()) + 1):
cell = self.cells.get(i, {}).get(j, None)
if not cell:
ET.SubElement(row, '{%s}table-cell' % TABLE_NS)
diff --git a/docbow_project/docbow/profile_views.py b/docbow_project/docbow/profile_views.py
index 1d41cb6..e703750 100644
--- a/docbow_project/docbow/profile_views.py
+++ b/docbow_project/docbow/profile_views.py
@@ -36,8 +36,7 @@ class ProfileView(cbv.FormWithRequestMixin, cbv.FormWithPostTarget, UpdateView):
return 'profile-validate' in self.request.POST
def form_valid(self, form):
- self.request.record('update-profile', 'modified its profile',
- **form.cleaned_data)
+ self.request.record('update-profile', 'modified its profile', **form.cleaned_data)
return super(ProfileView, self).form_valid(form)
@@ -51,17 +50,17 @@ class DelegateView(cbv.FormWithPostTarget, FormView):
super(DelegateView, self).__init__(*args, **kwargs)
def add_journal_to_delegations(self, delegations):
- delegations__to = [ delegation.to for delegation in delegations ]
- journals = Journal.objects \
- .for_objects(delegations__to) \
- .filter(tag__name='login') \
- .order_by('-time')[:len(delegations__to)*5]
+ delegations__to = [delegation.to for delegation in delegations]
+ journals = (
+ Journal.objects.for_objects(delegations__to)
+ .filter(tag__name='login')
+ .order_by('-time')[: len(delegations__to) * 5]
+ )
journal_by_users = dict()
for journal in journals:
for objectdata in journal.objectdata_set.all():
if objectdata.tag.name == 'delegate':
- journal_by_users.setdefault(objectdata.object_id, []) \
- .append(journal.time)
+ journal_by_users.setdefault(objectdata.object_id, []).append(journal.time)
for delegation in delegations:
delegation.journals = journal_by_users.get(delegation.to.id, [])[:5]
@@ -77,7 +76,7 @@ class DelegateView(cbv.FormWithPostTarget, FormView):
def get_form_kwargs(self, **kwargs):
kwargs = super(DelegateView, self).get_form_kwargs(**kwargs)
kwargs['user'] = self.request.user
- kwargs['delegatees'] = [ delegation.to for delegation in self.delegations ]
+ kwargs['delegatees'] = [delegation.to for delegation in self.delegations]
kwargs['request'] = self.request
return kwargs
@@ -85,48 +84,49 @@ class DelegateView(cbv.FormWithPostTarget, FormView):
request = self.request
delegation.delete()
delegate_user = delegation.to
- request.record('delete-delegation', 'deleted delegation '
- '{delegation} to user {delegated}',
- delegation=delegation.id,
- delegated=delegate_user)
+ request.record(
+ 'delete-delegation',
+ 'deleted delegation ' '{delegation} to user {delegated}',
+ delegation=delegation.id,
+ delegated=delegate_user,
+ )
user = request.user
# notify delegate
ctx = {
- 'user': utils.clean_ldap_user(user),
- 'delegate': delegate_user,
- 'to': [delegate_user.email],
- 'reply_to': user.email,
- }
+ 'user': utils.clean_ldap_user(user),
+ 'delegate': delegate_user,
+ 'to': [delegate_user.email],
+ 'reply_to': user.email,
+ }
models.Notification.objects.create(kind='delete-delegation', ctx=ctx)
- messages.info(request, _('Delegation %s supressed') %
- delegate_user)
- messages.info(request, _('%s has been notified.') %
- delegate_user.email)
- request.record('notify', 'notified {email} of '
- 'the deletion of its delegate user',
- email=delegate_user.email)
+ messages.info(request, _('Delegation %s supressed') % delegate_user)
+ messages.info(request, _('%s has been notified.') % delegate_user.email)
+ request.record(
+ 'notify', 'notified {email} of ' 'the deletion of its delegate user', email=delegate_user.email
+ )
# delete guest accounts
if delegation.guest_delegate:
- if 'mellon' in app_settings.settings.INSTALLED_APPS \
- and delegate_user.saml_identifiers.count():
+ if 'mellon' in app_settings.settings.INSTALLED_APPS and delegate_user.saml_identifiers.count():
err, json_data, err_desc = utils.a2_wscall(
urllib.parse.urljoin(
app_settings.settings.AUTHENTIC_URL,
- 'api/users/%s' % delegate_user.saml_identifiers.first().name_id
+ 'api/users/%s' % delegate_user.saml_identifiers.first().name_id,
),
- 'delete')
+ 'delete',
+ )
delegate_user.delete()
- request.record('delete-delegate', 'deleted delegate '
- 'user {username}, {first_name} {last_name}, '
- '({email})',
- username=delegate_user.username,
- first_name=delegate_user.first_name,
- last_name=delegate_user.last_name,
- email=delegate_user.email)
+ request.record(
+ 'delete-delegate',
+ 'deleted delegate ' 'user {username}, {first_name} {last_name}, ' '({email})',
+ username=delegate_user.username,
+ first_name=delegate_user.first_name,
+ last_name=delegate_user.last_name,
+ email=delegate_user.email,
+ )
return HttpResponseRedirect(self.success_url)
def is_post_target(self):
@@ -134,8 +134,7 @@ class DelegateView(cbv.FormWithPostTarget, FormView):
return True
for delegation in self.delegations:
username = delegation.to.username
- if 'delegate-delete-{username}.x'.format(username=username) in \
- self.request.POST:
+ if 'delegate-delete-{username}.x'.format(username=username) in self.request.POST:
return True
return False
@@ -145,8 +144,7 @@ class DelegateView(cbv.FormWithPostTarget, FormView):
return super(DelegateView, self).post(request, *args, **kwargs)
for delegation in self.delegations:
username = delegation.to.username
- if 'delegate-delete-{username}.x'.format(username=username) in \
- self.request.POST:
+ if 'delegate-delete-{username}.x'.format(username=username) in self.request.POST:
return self.delete(delegation)
return self.get(request, *args, **kwargs)
@@ -155,67 +153,70 @@ class DelegateView(cbv.FormWithPostTarget, FormView):
is_guest = not form.cleaned_data.get('existing_user')
ctx = {
'user': utils.clean_ldap_user(request.user),
- 'reply_to' :request.user.email,
+ 'reply_to': request.user.email,
'is_guest': is_guest,
}
if is_guest:
delegate_username = utils.get_free_delegation_number(request.user)
- delegate_user = User(username=delegate_username,
- first_name=form.cleaned_data.get('first_name', ''),
- last_name=form.cleaned_data.get('last_name', ''),
- email=form.cleaned_data.get('email', ''))
+ delegate_user = User(
+ username=delegate_username,
+ first_name=form.cleaned_data.get('first_name', ''),
+ last_name=form.cleaned_data.get('last_name', ''),
+ email=form.cleaned_data.get('email', ''),
+ )
delegate_user.set_unusable_password()
delegate_user.save()
- models.DocbowProfile.objects.create(user=delegate_user,
- is_guest=True, accept_notifications=app_settings.DEFAULT_ACCEPT_NOTIFICATIONS_FOR_GUEST)
- delegation, created = models.Delegation.objects.get_or_create(by=request.user,
- to=delegate_user)
+ models.DocbowProfile.objects.create(
+ user=delegate_user,
+ is_guest=True,
+ accept_notifications=app_settings.DEFAULT_ACCEPT_NOTIFICATIONS_FOR_GUEST,
+ )
+ delegation, created = models.Delegation.objects.get_or_create(by=request.user, to=delegate_user)
if 'mellon' in app_settings.settings.INSTALLED_APPS:
import mellon
+
ctx['sso'] = True
mellon.models.UserSAMLIdentifier.objects.create(
name_id=form.cleaned_data['name_id'],
- issuer=urllib.parse.urljoin(
- app_settings.settings.AUTHENTIC_URL, 'idp/saml2/metadata'
- ),
- user=delegate_user
+ issuer=urllib.parse.urljoin(app_settings.settings.AUTHENTIC_URL, 'idp/saml2/metadata'),
+ user=delegate_user,
)
- request.record('create-delegate', 'created delegate with '
- 'parameters {first_name} {last_name} <{email}>',
- **form.cleaned_data)
- ctx.update({
- 'password_reset_link':
- utils.make_password_reset_url(request, delegate_user),
- 'to': [form.cleaned_data['email']],
- 'delegate': delegate_user,
- 'delegation': delegation,
- })
- messages.info(request,
- _('New delegation to user %s created.') % delegate_user.username)
- messages.info(request,
- _('A notification was sent to %s about this new delegation') % delegate_user.email)
+ request.record(
+ 'create-delegate',
+ 'created delegate with ' 'parameters {first_name} {last_name} <{email}>',
+ **form.cleaned_data,
+ )
+ ctx.update(
+ {
+ 'password_reset_link': utils.make_password_reset_url(request, delegate_user),
+ 'to': [form.cleaned_data['email']],
+ 'delegate': delegate_user,
+ 'delegation': delegation,
+ }
+ )
+ messages.info(request, _('New delegation to user %s created.') % delegate_user.username)
+ messages.info(
+ request, _('A notification was sent to %s about this new delegation') % delegate_user.email
+ )
else:
delegate_user = form.cleaned_data.get('existing_user')
delegate_username = delegate_user.username
- delegation, created = models.Delegation.objects.get_or_create(by=request.user,
- to=delegate_user)
- ctx.update({
- 'to': models.all_emails(delegate_user),
- 'delegate': delegate_user,
- 'delegation': delegation,
- })
- messages.info(request,
- _('New delegation to user %s created.') %
- delegate_user.username)
- messages.info(request,
- _('A notification was sent to %s about this new delegation') % delegate_user.get_full_name())
+ delegation, created = models.Delegation.objects.get_or_create(by=request.user, to=delegate_user)
+ ctx.update(
+ {'to': models.all_emails(delegate_user), 'delegate': delegate_user, 'delegation': delegation,}
+ )
+ messages.info(request, _('New delegation to user %s created.') % delegate_user.username)
+ messages.info(
+ request,
+ _('A notification was sent to %s about this new delegation') % delegate_user.get_full_name(),
+ )
models.Notification.objects.create(kind='new-delegation', ctx=ctx)
- request.record('create-delegation', 'created delegation to '
- 'user {delegated}', delegated=delegate_user)
+ request.record(
+ 'create-delegation', 'created delegation to ' 'user {delegated}', delegated=delegate_user
+ )
return super(DelegateView, self).form_valid(form)
-
def get_context_data(self, **kwargs):
ctx = super(DelegateView, self).get_context_data(**kwargs)
ctx['delegations'] = self.delegations
@@ -255,10 +256,10 @@ class EmailView(cbv.FormWithPostTarget, UpdateView):
def form_valid(self, form):
messages.info(self.request, _('Email changed'))
- self.request.record('update-email', 'modified its email',
- **form.cleaned_data)
+ self.request.record('update-email', 'modified its email', **form.cleaned_data)
return super(EmailView, self).form_valid(form)
+
class NotificationPreferenceView(cbv.FormWithPostTarget, cbv.FormWithRequestMixin, FormView):
form_class = forms.NotificationPreferencesForm
template_name = 'docbow/notifications.html'
@@ -286,15 +287,15 @@ class FullProfileView(TemplateResponseMixin, View):
# multiplex all profile views
template_name = 'docbow/full-profile.html'
subviews = (
- ('notifications_form', NotificationPreferenceView),
- ('delegate_form', DelegateView),
+ ('notifications_form', NotificationPreferenceView),
+ ('delegate_form', DelegateView),
)
if 'mellon' not in app_settings.settings.INSTALLED_APPS:
subviews = subviews + (('password_change_form', PasswordChangeView),)
if app_settings.MOBILE_PHONE or app_settings.PERSONAL_EMAIL:
- subviews = (('profile_form', ProfileView),) + subviews
+ subviews = (('profile_form', ProfileView),) + subviews
if app_settings.EDIT_EMAIL and 'mellon' not in app_settings.settings.INSTALLED_APPS:
- subviews += (('email_form', EmailView),)
+ subviews += (('email_form', EmailView),)
def dispatch(self, request, *args, **kwargs):
if models.is_guest(request.user):
@@ -314,8 +315,7 @@ class FullProfileView(TemplateResponseMixin, View):
def get_view(self, var_name, view_class):
view = view_class()
- view.request, view.args, view.kwargs = \
- self.request, self.args, self.kwargs
+ view.request, view.args, view.kwargs = self.request, self.args, self.kwargs
if hasattr(view, 'get_object'):
view.object = view.get_object()
if self.request.method == 'POST' and view.is_post_target():
diff --git a/docbow_project/docbow/pyuca.py b/docbow_project/docbow/pyuca.py
index 3973a38..7bee33e 100644
--- a/docbow_project/docbow/pyuca.py
+++ b/docbow_project/docbow/pyuca.py
@@ -5,17 +5,17 @@
# http://jtauber.com/
# Copyright (c) 2006 James Tauber
-#
+#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
-#
+#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
-#
+#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -50,7 +50,6 @@ import os.path
class Trie:
-
def __init__(self):
self.root = [None, {}]
@@ -72,7 +71,6 @@ class Trie:
class Collator:
-
def __init__(self, filename):
self.table = Trie()
@@ -84,10 +82,10 @@ class Collator:
continue
if line.strip() == "":
continue
- line = line[:line.find("#")] + "\n"
- line = line[:line.find("%")] + "\n"
+ line = line[: line.find("#")] + "\n"
+ line = line[: line.find("%")] + "\n"
line = line.strip()
-
+
if line.startswith("@"):
pass
else:
@@ -98,20 +96,20 @@ class Collator:
while True:
begin = x.find("[")
if begin == -1:
- break
+ break
end = x[begin:].find("]")
- collElement = x[begin:begin+end+1]
- x = x[begin + 1:]
-
+ collElement = x[begin : begin + end + 1]
+ x = x[begin + 1 :]
+
alt = collElement[1]
chars = collElement[2:-1].split(".")
-
+
collElements.append((alt, chars))
integer_points = [int(ch, 16) for ch in charList]
self.table.add(integer_points, collElements)
def sort_key(self, string):
-
+
collation_elements = []
lookup_key = [ord(ch) for ch in string]
@@ -121,17 +119,18 @@ class Collator:
# @@@
raise ValueError(map(hex, lookup_key))
collation_elements.extend(value)
-
+
sort_key = []
-
+
for level in range(4):
if level:
- sort_key.append(0) # level separator
+ sort_key.append(0) # level separator
for element in collation_elements:
ce_l = int(element[1][level], 16)
if ce_l:
sort_key.append(ce_l)
-
+
return tuple(sort_key)
+
collator = Collator(os.path.join(os.path.dirname(__file__), 'allkeys.txt'))
diff --git a/docbow_project/docbow/signals.py b/docbow_project/docbow/signals.py
index 898a8c8..ce664ab 100644
--- a/docbow_project/docbow/signals.py
+++ b/docbow_project/docbow/signals.py
@@ -32,8 +32,10 @@ def logged_out_handler(sender, request, user, **kwargs):
user = user.user
django_journal.record('logout', msg, user=user, ip=extra['ip'], **kwargs)
+
do_log = True
+
def modified_data(sender, instance, created, raw, using, **kwargs):
global do_log
if using != 'default':
@@ -51,8 +53,9 @@ def modified_data(sender, instance, created, raw, using, **kwargs):
else:
tag = 'modify'
msg = '{user} modified {model} {instance}'
- django_journal.record(tag, msg, user=extra['user'], ip=extra['ip'],
- model=sender._meta.model_name, instance=instance)
+ django_journal.record(
+ tag, msg, user=extra['user'], ip=extra['ip'], model=sender._meta.model_name, instance=instance
+ )
def list_m2m_changed_handler(sender, instance, action, reverse, model, pk_set, using, **kwargs):
@@ -75,8 +78,8 @@ def list_m2m_changed_handler(sender, instance, action, reverse, model, pk_set, u
elif action == 'post_remove':
msg = N_('removed user {member} from mailing list {list}')
for user in users:
- django_journal.record(action, msg, list=instance, member=user,
- ip=extra['ip'], user=extra['user'])
+ django_journal.record(action, msg, list=instance, member=user, ip=extra['ip'], user=extra['user'])
+
@receiver(m2m_changed, sender=User.groups.through)
def groups_changed(sender, instance, action, **kwargs):
@@ -91,10 +94,10 @@ def groups_changed(sender, instance, action, **kwargs):
finally:
do_log = True
+
user_logged_in.connect(logged_in_handler)
user_logged_out.connect(logged_out_handler)
db_post_save.connect(modified_data, sender=models.MailingList)
db_post_save.connect(modified_data, sender=auth_models.User)
db_post_save.connect(modified_data, sender=auth_models.Group)
-m2m_changed.connect(list_m2m_changed_handler,
- sender=models.MailingList.members.through)
+m2m_changed.connect(list_m2m_changed_handler, sender=models.MailingList.members.through)
diff --git a/docbow_project/docbow/sms_carrier_ovh.py b/docbow_project/docbow/sms_carrier_ovh.py
index d670f28..a098707 100644
--- a/docbow_project/docbow/sms_carrier_ovh.py
+++ b/docbow_project/docbow/sms_carrier_ovh.py
@@ -10,6 +10,7 @@ from django_journal import journal as django_journal
logger = logging.getLogger(__name__)
+
class OVHSMSCarrier(object):
URL = 'https://www.ovh.com/cgi-bin/sms/http2sms.cgi'
SMS_CLASS = 1
@@ -19,29 +20,33 @@ class OVHSMSCarrier(object):
sms_class = sms_class or self.SMS_CLASS
to = ','.join([t.replace('+', '00') for t in to])
params = {
- 'account': settings.OVH_SMS_ACCOUNT,
- 'login': settings.OVH_SMS_LOGIN,
- 'password': settings.OVH_SMS_PASSWORD,
- 'from': settings.OVH_SMS_FROM,
- 'to': to,
- 'message': payload,
- 'contentType': 'text/json',
- 'class': sms_class,
+ 'account': settings.OVH_SMS_ACCOUNT,
+ 'login': settings.OVH_SMS_LOGIN,
+ 'password': settings.OVH_SMS_PASSWORD,
+ 'from': settings.OVH_SMS_FROM,
+ 'to': to,
+ 'message': payload,
+ 'contentType': 'text/json',
+ 'class': sms_class,
}
if no_stop:
params['no_stop'] = 1
- django_journal.error_record('ovh-sms',
- 'OVH SMS CARRIER: sending message {message} to {numbers}',
- message=message, numbers=to)
+ django_journal.error_record(
+ 'ovh-sms', 'OVH SMS CARRIER: sending message {message} to {numbers}', message=message, numbers=to
+ )
stream = urlopen('%s?%s' % (self.URL, urlencode(params)))
result = json.loads(stream.read())
if 100 <= result['status'] < 200:
credit_alert = getattr(settings, 'OVH_SMS_CREDIT_ALERT', 100)
credit_left = result['creditLeft']
if credit_left < credit_alert:
- django_journal.error_record('error', 'OVH SMS CARRIER: credit '
- 'left({credit_left}) < credit alert limit({credit_alert})',
- credit_left=credit_left, credit_alert=credit_alert)
+ django_journal.error_record(
+ 'error',
+ 'OVH SMS CARRIER: credit ' 'left({credit_left}) < credit alert limit({credit_alert})',
+ credit_left=credit_left,
+ credit_alert=credit_alert,
+ )
else:
- django_journal.error_record('error', 'OVH SMS CARRIER: status "{status}"'
- 'message "{message}"', **result)
+ django_journal.error_record(
+ 'error', 'OVH SMS CARRIER: status "{status}"' 'message "{message}"', **result
+ )
diff --git a/docbow_project/docbow/sql.py b/docbow_project/docbow/sql.py
index f0e3e2f..5f3f7a5 100644
--- a/docbow_project/docbow/sql.py
+++ b/docbow_project/docbow/sql.py
@@ -34,17 +34,19 @@ def get_complex_join(qs, sql, params):
def get_unseen_documents_count(related_users, user):
query = GET_UNSEEN_DOCUMENTS_SQL % ('(%s)' % ', '.join(['%s'] * len(related_users)))
return get_sql_count(
- query, (False,) +
- tuple(related_users.values_list('id', flat=True)) + (user.pk, user.pk, False, user.pk, True)
+ query,
+ (False,)
+ + tuple(related_users.values_list('id', flat=True))
+ + (user.pk, user.pk, False, user.pk, True),
)
def get_documents(qs, related_users, user, outbox):
query = GET_DOCUMENTS_SQL % ('(%s)' % ', '.join(['%s'] * len(related_users)))
qs = get_complex_join(
- qs, query,
- (outbox, ) + tuple(
- related_users.values_list('id', flat=True)) + (user.pk, False, user.pk, True)
+ qs,
+ query,
+ (outbox,) + tuple(related_users.values_list('id', flat=True)) + (user.pk, False, user.pk, True),
)
qs = qs.prefetch_related('to_list', 'to_user', 'mailboxes__owner')
qs = qs.extra(select={'seen': SEEN_DOCUMENT % user.pk})
@@ -54,9 +56,9 @@ def get_documents(qs, related_users, user, outbox):
def get_trash_documents(qs, related_users, user, outbox):
query = GET_TRASH_DOCUMENTS_SQL % ('(%s)' % ', '.join(['%s'] * len(related_users)))
qs = get_complex_join(
- qs, query,
- (outbox, ) + tuple(
- related_users.values_list('id', flat=True)) + (user.pk, False, user.pk, True)
+ qs,
+ query,
+ (outbox,) + tuple(related_users.values_list('id', flat=True)) + (user.pk, False, user.pk, True),
)
qs = qs.prefetch_related('to_list', 'to_user', 'mailboxes__owner')
return qs
diff --git a/docbow_project/docbow/tables.py b/docbow_project/docbow/tables.py
index 3c3e3c5..02806bd 100644
--- a/docbow_project/docbow/tables.py
+++ b/docbow_project/docbow/tables.py
@@ -10,28 +10,25 @@ from docbow_project.docbow import models
class MailboxTable(tables.Table):
-
class Meta:
model = models.Document
attrs = {"class": "paleblue"}
+
# FIXEM: translation in inline templates are ignored
_('self')
+
class OutboxCsvTable(tables.Table):
- official_sender = tables.Column(accessor='sender.get_full_name',
- verbose_name=_('official_sender_header'))
- recipients = tables.Column(accessor='recipients',
- verbose_name=_('recipients_header'), orderable=False)
+ official_sender = tables.Column(accessor='sender.get_full_name', verbose_name=_('official_sender_header'))
+ recipients = tables.Column(accessor='recipients', verbose_name=_('recipients_header'), orderable=False)
real_sender = tables.TemplateColumn(
- '{% load i18n %}{% if record.real_sender %}{{ record.real_sender }}{% else %}{% trans "self" %}{% endif %}',
- verbose_name=_('real_sender_header'))
- filetype = tables.Column(accessor='filetype',
- verbose_name=_('type_header'))
- filenames = tables.Column(accessor='filenames',
- verbose_name=_('filename_header'), orderable=False)
- date = tables.Column(accessor='date',
- verbose_name=_('date_header'))
+ '{% load i18n %}{% if record.real_sender %}{{ record.real_sender }}{% else %}{% trans "self" %}{% endif %}',
+ verbose_name=_('real_sender_header'),
+ )
+ filetype = tables.Column(accessor='filetype', verbose_name=_('type_header'))
+ filenames = tables.Column(accessor='filenames', verbose_name=_('filename_header'), orderable=False)
+ date = tables.Column(accessor='date', verbose_name=_('date_header'))
class Meta:
model = models.Document
@@ -40,27 +37,27 @@ class OutboxCsvTable(tables.Table):
attrs = {"class": "paleblue mailbox-table"}
empty_text = _('No message')
+
SELECT_ALL = mark_safe('')
class OutboxBaseTable(tables.Table):
- official_sender = tables.Column(accessor='sender.get_full_name',
- order_by=('sender__last_name',
- 'sender__first_name',
- 'sender__username'),
- verbose_name=_('official_sender_header'))
- recipients = tables.Column(accessor='recipients',
- verbose_name=_('recipients_header'), orderable=False)
+ official_sender = tables.Column(
+ accessor='sender.get_full_name',
+ order_by=('sender__last_name', 'sender__first_name', 'sender__username'),
+ verbose_name=_('official_sender_header'),
+ )
+ recipients = tables.Column(accessor='recipients', verbose_name=_('recipients_header'), orderable=False)
real_sender = tables.TemplateColumn(
- '{% load i18n %}{% if record.real_sender %}{{ record.real_sender }}{% else %}{% trans "self" %}{% endif %}',
- order_by=('real_sender',),
- verbose_name=_('real_sender_header'))
- filetype = tables.Column(accessor='filetype',
- verbose_name=_('type_header'))
- filenames = tables.Column(accessor='filenames',
- verbose_name=_('filename_header'), orderable=False)
- date = tables.TemplateColumn('{% load humantime %}{{ record.date|humantime }}',
- verbose_name=_('date_header'))
+ '{% load i18n %}{% if record.real_sender %}{{ record.real_sender }}{% else %}{% trans "self" %}{% endif %}',
+ order_by=('real_sender',),
+ verbose_name=_('real_sender_header'),
+ )
+ filetype = tables.Column(accessor='filetype', verbose_name=_('type_header'))
+ filenames = tables.Column(accessor='filenames', verbose_name=_('filename_header'), orderable=False)
+ date = tables.TemplateColumn(
+ '{% load humantime %}{{ record.date|humantime }}', verbose_name=_('date_header')
+ )
class Meta:
model = models.Document
@@ -73,8 +70,7 @@ class OutboxBaseTable(tables.Table):
class OutboxTrashTable(OutboxBaseTable):
restore = tables.TemplateColumn(
- template_name='docbow/outbox_restore_column.html',
- orderable=False, verbose_name=_('Restore')
+ template_name='docbow/outbox_restore_column.html', orderable=False, verbose_name=_('Restore')
)
class Meta:
@@ -87,11 +83,13 @@ class OutboxTrashTable(OutboxBaseTable):
class OutboxTable(OutboxBaseTable):
select = tables.TemplateColumn(
- '',
- orderable=False, verbose_name=SELECT_ALL)
- delete = tables.TemplateColumn(template_name='docbow/outbox_delete_column.html',
- orderable=False,
- verbose_name=' ')
+ '',
+ orderable=False,
+ verbose_name=SELECT_ALL,
+ )
+ delete = tables.TemplateColumn(
+ template_name='docbow/outbox_delete_column.html', orderable=False, verbose_name=' '
+ )
class Meta:
model = models.Document
@@ -102,16 +100,10 @@ class OutboxTable(OutboxBaseTable):
class InboxCsvTable(tables.Table):
- filetype = tables.Column(
- accessor='filetype',
- verbose_name=_('type_header'))
- filenames = tables.Column(
- accessor='filenames', verbose_name=_('filename_header'),
- orderable=False)
- sender = tables.Column(
- accessor='sender', verbose_name=_('sender_header'))
- date = tables.Column(
- accessor='date', verbose_name=_('date_header'))
+ filetype = tables.Column(accessor='filetype', verbose_name=_('type_header'))
+ filenames = tables.Column(accessor='filenames', verbose_name=_('filename_header'), orderable=False)
+ sender = tables.Column(accessor='sender', verbose_name=_('sender_header'))
+ date = tables.Column(accessor='date', verbose_name=_('date_header'))
class Meta:
model = models.Document
@@ -120,27 +112,31 @@ class InboxCsvTable(tables.Table):
class InboxBaseTable(tables.Table):
- seen = tables.BooleanColumn(accessor='seen', yesno=u' ,✔',
- verbose_name=' ', orderable=False)
- filetype = tables.Column(
- accessor='filetype',
- verbose_name=_('type_header'))
- filenames = tables.Column(
- accessor='filenames', verbose_name=_('filename_header'),
- orderable=False)
+ seen = tables.BooleanColumn(accessor='seen', yesno=u' ,✔', verbose_name=' ', orderable=False)
+ filetype = tables.Column(accessor='filetype', verbose_name=_('type_header'))
+ filenames = tables.Column(accessor='filenames', verbose_name=_('filename_header'), orderable=False)
recipients = tables.TemplateColumn(
- '''{% load docbow %}{% for recipient_user in record.delivered_to|intersect:related_users %}
+ '''{% load docbow %}{% for recipient_user in record.delivered_to|intersect:related_users %}
{{ recipient_user|username }}{% if not forloop.last %},{% endif %}
-{% endfor %}''', orderable=False, verbose_name=_('recipients_header'))
- sender = tables.TemplateColumn('{{ record.sender_display }}',
- order_by=('sender__last_name', 'sender__first_name', 'sender__username'),
- verbose_name=_('sender_header'))
- date = tables.TemplateColumn('{% load humantime %}{{ record.date|humantime }}',
- verbose_name=_('date_header'))
+{% endfor %}''',
+ orderable=False,
+ verbose_name=_('recipients_header'),
+ )
+ sender = tables.TemplateColumn(
+ '{{ record.sender_display }}',
+ order_by=('sender__last_name', 'sender__first_name', 'sender__username'),
+ verbose_name=_('sender_header'),
+ )
+ date = tables.TemplateColumn(
+ '{% load humantime %}{{ record.date|humantime }}', verbose_name=_('date_header')
+ )
class Meta:
model = models.Document
- fields = ('seen', 'filetype',)
+ fields = (
+ 'seen',
+ 'filetype',
+ )
attrs = {"class": "paleblue mailbox-table refresh", "id": "outbox-table"}
empty_text = _('No message')
@@ -148,26 +144,36 @@ class InboxBaseTable(tables.Table):
class InboxTrashTable(InboxBaseTable):
restore = tables.TemplateColumn(
- template_name='docbow/inbox_restore_column.html',
- orderable=False, verbose_name=_('Restore')
+ template_name='docbow/inbox_restore_column.html', orderable=False, verbose_name=_('Restore')
)
class Meta:
model = models.Document
- fields = ('select', 'seen', 'filetype',)
+ fields = (
+ 'select',
+ 'seen',
+ 'filetype',
+ )
attrs = {"class": "paleblue mailbox-table refresh", "id": "inbox-table"}
empty_text = _('No message')
class InboxTable(InboxBaseTable):
select = tables.TemplateColumn(
- '',
- verbose_name=SELECT_ALL, orderable=False)
- delete = tables.TemplateColumn(template_name='docbow/inbox_delete_column.html',
- orderable=False, verbose_name=' ')
+ '',
+ verbose_name=SELECT_ALL,
+ orderable=False,
+ )
+ delete = tables.TemplateColumn(
+ template_name='docbow/inbox_delete_column.html', orderable=False, verbose_name=' '
+ )
class Meta:
model = models.Document
- fields = ('select', 'seen', 'filetype',)
+ fields = (
+ 'select',
+ 'seen',
+ 'filetype',
+ )
attrs = {"class": "paleblue mailbox-table refresh", "id": "outbox-table"}
empty_text = _('No message')
diff --git a/docbow_project/docbow/templatetags/docbow.py b/docbow_project/docbow/templatetags/docbow.py
index d4eb035..f31ca0b 100644
--- a/docbow_project/docbow/templatetags/docbow.py
+++ b/docbow_project/docbow/templatetags/docbow.py
@@ -8,6 +8,7 @@ from .. import views, models, app_settings, sql
register = template.Library()
+
def paginator(context):
"""
To be used in conjunction with the object_list generic view.
@@ -20,7 +21,7 @@ def paginator(context):
page = context['page']
hits = page.paginator.count
pn = page.number
- link_to_last_page = (page.paginator.num_pages > 2) and (pn < (page.paginator.num_pages-1))
+ link_to_last_page = (page.paginator.num_pages > 2) and (pn < (page.paginator.num_pages - 1))
return {
'hits': hits,
'page_number': page.number,
@@ -28,14 +29,16 @@ def paginator(context):
'last_page': page.paginator.num_pages,
'first': page.start_index(),
'last': page.end_index(),
- 'previous': page.number-1,
- 'next': page.number+1,
+ 'previous': page.number - 1,
+ 'next': page.number + 1,
'has_next': page.has_next(),
'has_previous': page.has_previous(),
}
+
register.inclusion_tag('docbow/paginator.html', takes_context=True)(paginator)
+
def menu(context):
request = context.get('request')
here = context.get('view_name')
@@ -60,47 +63,63 @@ def menu(context):
view_name = slugify(view_name)
else:
url = reverse(view_name)
- docbow_menu.append({ 'view_name': view_name.replace(':', '-'),
- 'url': url, 'caption': caption, 'count': count,
- 'current': current})
- return { 'menus': docbow_menu }
+ docbow_menu.append(
+ {
+ 'view_name': view_name.replace(':', '-'),
+ 'url': url,
+ 'caption': caption,
+ 'count': count,
+ 'current': current,
+ }
+ )
+ return {'menus': docbow_menu}
+
register.inclusion_tag('docbow/menu.html', takes_context=True)(menu)
+
def username(value):
return models.username(value)
+
+
register.filter(username)
+
def doc_real_sender(document):
return document.real_sender or models.username(document.sender)
+
+
register.filter(doc_real_sender)
+
def frfilesizeformat(value):
- if value < 1024*1024:
+ if value < 1024 * 1024:
value = value / 1024.0
unit = _('kB')
else:
- value = value / (1024*1024.0)
+ value = value / (1024 * 1024.0)
unit = _('MB')
return "%.1f %s" % (value, unit)
+
register.filter(frfilesizeformat)
+
def humantargets(value):
user_human_to = value.user_human_to()
group_human_to = value.group_human_to()
l1 = map(lambda x: _('to %s') % x, user_human_to)
if len(user_human_to) > 1:
- p1 = _('%(one)s and %(two)s') % { 'one': ', '.join(l1[0:-1]), 'two': l1[-1] }
+ p1 = _('%(one)s and %(two)s') % {'one': ', '.join(l1[0:-1]), 'two': l1[-1]}
elif user_human_to:
p1 = l1[0]
l2 = map(lambda x: _('to list %s') % x, group_human_to)
if len(group_human_to) > 1:
- p2 = _('%(one)s and %(two)s') % { 'one': ', '.join(l2[0:-1]), 'two': l2[-1] }
+ p2 = _('%(one)s and %(two)s') % {'one': ', '.join(l2[0:-1]), 'two': l2[-1]}
elif group_human_to:
p2 = l2[0]
if l1 and l2:
- return _('%(one)s and to lists %(two)s') % { 'one': p1, 'two': p2 }
+ return _('%(one)s and to lists %(two)s') % {'one': p1, 'two': p2}
elif l1:
return p1
elif l2:
@@ -108,11 +127,14 @@ def humantargets(value):
else:
return ''
+
register.filter(humantargets)
+
def nonbreakinghyphen(value):
return value.replace('-', '‑')
+
register.filter(nonbreakinghyphen)
@@ -121,11 +143,13 @@ def order_by(queryset, args):
args = [x.strip() for x in args.split(',')]
return queryset.order_by(*args)
+
@register.filter_function
def intersect(iterable1, iterable2):
iterable2 = set(iterable2)
return [it for it in iterable1 if it in iterable2]
+
@register.filter
def is_checkbox(field):
return field.field.widget.__class__.__name__.lower() == "checkboxinput"
diff --git a/docbow_project/docbow/unicodecsv.py b/docbow_project/docbow/unicodecsv.py
index 75c0f7a..1d74bb6 100644
--- a/docbow_project/docbow/unicodecsv.py
+++ b/docbow_project/docbow/unicodecsv.py
@@ -4,6 +4,7 @@ import csv
from django.utils.encoding import force_str, force_text
from django.utils.six import StringIO
+
class UnicodeWriter(object):
"""
Like UnicodeDictWriter, but takes lists rather than dictionaries.
@@ -21,6 +22,7 @@ class UnicodeWriter(object):
])
fp.close()
"""
+
def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds):
# Redirect output to a queue
self.queue = StringIO()
@@ -45,6 +47,7 @@ class UnicodeWriter(object):
for row in rows:
self.writerow(row)
+
class UnicodeDictWriter(UnicodeWriter):
"""
A CSV writer that produces Excel-compatibly CSV files from unicode data.
@@ -67,8 +70,7 @@ class UnicodeDictWriter(UnicodeWriter):
Initially derived from http://docs.python.org/lib/csv-examples.html
"""
- def __init__(self, f, fields, dialect=csv.excel_tab,
- encoding="utf-16", **kwds):
+ def __init__(self, f, fields, dialect=csv.excel_tab, encoding="utf-16", **kwds):
super(UnicodeDictWriter, self).__init__(f, dialect, encoding, **kwds)
self.fields = fields
diff --git a/docbow_project/docbow/upload_urls.py b/docbow_project/docbow/upload_urls.py
index ec28e82..d4a5113 100644
--- a/docbow_project/docbow/upload_urls.py
+++ b/docbow_project/docbow/upload_urls.py
@@ -7,15 +7,12 @@ urlpatterns = [
url(
r'^(?P[a-zA-Z0-9-]+)/(?P[0-9]+)/$',
docbow_project.docbow.upload_views.upload,
- name='upload'
- ),
- url(
- r'^(?P[a-zA-Z0-9-]+)/$',
- docbow_project.docbow.upload_views.upload,
- name='upload'
+ name='upload',
),
+ url(r'^(?P[a-zA-Z0-9-]+)/$', docbow_project.docbow.upload_views.upload, name='upload'),
url(
r'^(?P[a-zA-Z0-9-]+)/(?P[^/]+)$',
docbow_project.docbow.upload_views.upload_file,
- name='uploaded'),
+ name='uploaded',
+ ),
]
diff --git a/docbow_project/docbow/upload_views.py b/docbow_project/docbow/upload_views.py
index ec135b8..53b8869 100644
--- a/docbow_project/docbow/upload_views.py
+++ b/docbow_project/docbow/upload_views.py
@@ -14,6 +14,7 @@ from django.utils.translation import ugettext_lazy as _
from .models import FileTypeAttachedFileKind
from . import app_settings
+
def get_paths_for_id(upload_id):
storage = DefaultStorage()
path = os.path.join('upload', upload_id)
@@ -21,6 +22,7 @@ def get_paths_for_id(upload_id):
return []
return list(storage.listdir(path)[1])
+
def get_files_for_id(upload_id):
storage = DefaultStorage()
path = os.path.join('upload', upload_id)
@@ -30,12 +32,13 @@ def get_files_for_id(upload_id):
name = os.path.basename(filepath)
yield storage.open(os.path.join(path, name))
+
def get_data_for_id(upload_id):
for file_object in get_files_for_id(upload_id):
name = os.path.basename(file_object.name)
url = reverse('uploaded', args=[upload_id, name])
- yield { 'name': name, 'size': file_object.size, 'url': url,
- 'delete_url': url, 'delete_type': 'DELETE' }
+ yield {'name': name, 'size': file_object.size, 'url': url, 'delete_url': url, 'delete_type': 'DELETE'}
+
def response_mimetype(request):
if "application/json" in request.META['HTTP_ACCEPT']:
@@ -43,13 +46,13 @@ def response_mimetype(request):
else:
return "text/plain"
+
class JSONResponse(HttpResponse):
"""JSON response class."""
- def __init__(self,obj='',json_opts={},mimetype="application/json",*args,**kwargs):
- content = json.dumps(obj,**json_opts)
- super(JSONResponse,self).__init__(content,mimetype,*args,**kwargs)
-
+ def __init__(self, obj='', json_opts={}, mimetype="application/json", *args, **kwargs):
+ content = json.dumps(obj, **json_opts)
+ super(JSONResponse, self).__init__(content, mimetype, *args, **kwargs)
@csrf_exempt
@@ -75,32 +78,36 @@ def upload(request, transaction_id, file_kind=None):
if uploaded_file.size > app_settings.MAX_FILE_SIZE:
message = _('File is too big, limit is %(max_file_size)s bytes')
message = message % {'max_file_size': app_settings.MAX_FILE_SIZE}
- data.append({'name': uploaded_file.name, 'error': force_text(message) })
+ data.append({'name': uploaded_file.name, 'error': force_text(message)})
continue
if file_kind:
if not file_kind.match_file(uploaded_file):
- message = _('invalid file type, check required '
- 'file types for this field')
- data.append({'name': uploaded_file.name, 'error': force_text(message) })
+ message = _('invalid file type, check required ' 'file types for this field')
+ data.append({'name': uploaded_file.name, 'error': force_text(message)})
continue
uploaded_file.open()
if len(uploaded_file.name) > max_filename_length:
- message = _('filename too long, only %d characters allowed') % \
- max_filename_length
- data.append({'name': uploaded_file.name, 'error': force_text(message) })
+ message = _('filename too long, only %d characters allowed') % max_filename_length
+ data.append({'name': uploaded_file.name, 'error': force_text(message)})
continue
if max_files:
count = len(get_paths_for_id(transaction_id))
if count >= max_files:
message = _('too much file attached, delete to add a new one')
- data.append({'name': uploaded_file.name, 'error': force_text(message) })
+ data.append({'name': uploaded_file.name, 'error': force_text(message)})
continue
path = os.path.join('upload', str(transaction_id), uploaded_file.name)
filename = storage.save(path, uploaded_file)
url = '%s%s' % (url, os.path.basename(filename))
- data.append({'name': uploaded_file.name, 'size':
- uploaded_file.size, 'url': url, 'delete_url': url,
- 'delete_type': "DELETE"})
+ data.append(
+ {
+ 'name': uploaded_file.name,
+ 'size': uploaded_file.size,
+ 'url': url,
+ 'delete_url': url,
+ 'delete_type': "DELETE",
+ }
+ )
response = JSONResponse(data, {}, response_mimetype(request))
response['Content-Disposition'] = 'inline; filename=files.json'
return response
@@ -110,6 +117,7 @@ def upload(request, transaction_id, file_kind=None):
response['Content-Disposition'] = 'inline; filename=files.json'
return response
+
def file_response(file_object):
if not isinstance(file_object, File):
file_object = File(file_object)
@@ -117,6 +125,7 @@ def file_response(file_object):
response['Content-disposition'] = 'attachment'
return response
+
@csrf_exempt
def upload_file(request, transaction_id, filename):
storage = DefaultStorage()
diff --git a/docbow_project/docbow/urls.py b/docbow_project/docbow/urls.py
index 8251079..0ccfe2b 100644
--- a/docbow_project/docbow/urls.py
+++ b/docbow_project/docbow/urls.py
@@ -7,71 +7,90 @@ import docbow_project.docbow.views
urlpatterns = [
url(r'^$', docbow_project.docbow.views.homepage, name='homepage'),
url(r'^profile/$', docbow_project.docbow.views.profile, name='profile'),
-
# inbox
-
url(r'^inbox/$', docbow_project.docbow.views.inbox_view, name='inbox'),
url(r'^inbox/trash/$', docbow_project.docbow.views.inbox_trash_view, name='inbox-trash'),
- url(r'^inbox_by_document/(?P\d+)/$',
+ url(
+ r'^inbox_by_document/(?P\d+)/$',
docbow_project.docbow.views.inbox_by_document,
- name='inbox-by-document-message'),
- url(r'^inbox/(?P\d+)/$',
- docbow_project.docbow.views.message, name='inbox-message',
- kwargs={'outbox': False}),
- url(r'^inbox/(?P\d+)/delete/$',
+ name='inbox-by-document-message',
+ ),
+ url(
+ r'^inbox/(?P\d+)/$',
+ docbow_project.docbow.views.message,
+ name='inbox-message',
+ kwargs={'outbox': False},
+ ),
+ url(
+ r'^inbox/(?P\d+)/delete/$',
docbow_project.docbow.views.delete,
- name='inbox-message-delete'),
- url(r'^inbox/(?P\d+)/restore/$',
+ name='inbox-message-delete',
+ ),
+ url(
+ r'^inbox/(?P\d+)/restore/$',
docbow_project.docbow.views.restore,
- name='inbox-message-restore', kwargs={'outbox': False}),
- url(r'^inbox/(?P\d+)/(?P\d+)/.*$',
+ name='inbox-message-restore',
+ kwargs={'outbox': False},
+ ),
+ url(
+ r'^inbox/(?P\d+)/(?P\d+)/.*$',
docbow_project.docbow.views.message_attached_file,
- name='inbox-message-attached-file'),
- url(r'^inbox/(?P\d+)/allfiles/$',
+ name='inbox-message-attached-file',
+ ),
+ url(
+ r'^inbox/(?P\d+)/allfiles/$',
docbow_project.docbow.views.message_all_files,
- name='outbox-message-attached-file'),
+ name='outbox-message-attached-file',
+ ),
url(r'^inbox/csv$', docbow_project.docbow.views.inbox_csv, name='inbox-csv'),
url(r'^inbox/ods$', docbow_project.docbow.views.inbox_ods, name='inbox-ods'),
-
# outbox
-
url(r'^outbox/$', docbow_project.docbow.views.outbox_view, name='outbox'),
url(r'^outbox/trash/$', docbow_project.docbow.views.outbox_trash_view, name='outbox-trash'),
- url(r'^outbox/(?P\d+)/$',
- docbow_project.docbow.views.message, name='outbox-message',
- kwargs={'outbox': True}),
- url(r'^outbox/(?P\d+)/delete/$',
+ url(
+ r'^outbox/(?P\d+)/$',
+ docbow_project.docbow.views.message,
+ name='outbox-message',
+ kwargs={'outbox': True},
+ ),
+ url(
+ r'^outbox/(?P\d+)/delete/$',
docbow_project.docbow.views.delete,
- name='outbox-message-delete', kwargs={'outbox': True}),
- url(r'^outbox/(?P\d+)/restore/$',
+ name='outbox-message-delete',
+ kwargs={'outbox': True},
+ ),
+ url(
+ r'^outbox/(?P\d+)/restore/$',
docbow_project.docbow.views.restore,
- name='outbox-message-restore', kwargs={'outbox': True}),
- url(r'^outbox/(?P\d+)/(?P\d+)/.*$',
+ name='outbox-message-restore',
+ kwargs={'outbox': True},
+ ),
+ url(
+ r'^outbox/(?P\d+)/(?P\d+)/.*$',
docbow_project.docbow.views.message_attached_file,
- name='outbox-message-attached-file', kwargs={'outbox': True}),
- url(r'^outbox/(?P\d+)/allfiles/$',
+ name='outbox-message-attached-file',
+ kwargs={'outbox': True},
+ ),
+ url(
+ r'^outbox/(?P\d+)/allfiles/$',
docbow_project.docbow.views.message_all_files,
- name='outbox-message-attached-file', kwargs={'outbox': True}),
+ name='outbox-message-attached-file',
+ kwargs={'outbox': True},
+ ),
url(r'^outbox/csv$', docbow_project.docbow.views.outbox_csv, name='outbox-csv'),
url(r'^outbox/ods$', docbow_project.docbow.views.outbox_ods, name='outbox-ods'),
-
-
- url(r'^send_file/$',
- docbow_project.docbow.views.send_file_selector, name='send-file-selector'),
- url(r'^send_file/(?P\d+)/$',
- docbow_project.docbow.views.send_file, name='send-file'),
+ url(r'^send_file/$', docbow_project.docbow.views.send_file_selector, name='send-file-selector'),
+ url(r'^send_file/(?P\d+)/$', docbow_project.docbow.views.send_file, name='send-file'),
url(r'^help/$', docbow_project.docbow.views.help, name='help'),
url(r'^help/(?P[a-zA-Z0-9-/\.]+)$', docbow_project.docbow.views.help, name='help'),
url(r'^contact/$', docbow_project.docbow.views.contact, name='contact'),
url(r'^logout/$', docbow_project.docbow.views.logout, name='logout'),
url(r'^delegate/$', docbow_project.docbow.views.delegate, name='delegate'),
url(r'^upload/', include('docbow_project.docbow.upload_urls')),
- url(r'^su/(?P.*)/$',
- docbow_project.docbow.views.su, {'redirect_url': '/'}),
+ url(r'^su/(?P.*)/$', docbow_project.docbow.views.su, {'redirect_url': '/'}),
url(r'^mailing-lists/', docbow_project.docbow.views.mailing_lists, name='mailing-lists'),
url(r'^search-inbox/', docbow_project.docbow.views.search_inbox, name='search-inbox'),
url(r'^search-outbox/', docbow_project.docbow.views.search_outbox, name='search-outbox'),
-
]
for custom in ('docbow_project.pfwb', 'docbow_project.pw'):
diff --git a/docbow_project/docbow/utils.py b/docbow_project/docbow/utils.py
index 426fcc8..191b8ca 100644
--- a/docbow_project/docbow/utils.py
+++ b/docbow_project/docbow/utils.py
@@ -13,19 +13,22 @@ import requests
from docbow_project.docbow import app_settings
+
def truncate_filename(file_name):
'''Truncate filename (without extension) and append original extension'''
base_name = os.path.basename(file_name)
base, ext = os.path.splitext(base_name)
- base = base[:app_settings.TRUNCATE_FILENAME]
+ base = base[: app_settings.TRUNCATE_FILENAME]
return base + ext
+
def clean_ldap_user(user):
'''Clean references to module in django-auth-ldap User model, allowing
pickling of the instances.'''
user.ldap_user = None
return user
+
def match_mime_type(t1, t2):
if t1.endswith('/*') or t2.endswith('/*'):
t1 = t1.split('/')[0]
@@ -80,13 +83,15 @@ def make_password_reset_url(request, user):
uid = urlsafe_base64_encode(force_bytes(user.id))
token = default_token_generator.make_token(user)
return request.build_absolute_uri(
- reverse('auth_password_reset_confirm',
- kwargs={'uidb64': uid, 'token': token}))
+ reverse('auth_password_reset_confirm', kwargs={'uidb64': uid, 'token': token})
+ )
+
def date_to_aware_datetime(date):
return timezone.make_aware(
- datetime.datetime(date.year, date.month, date.day),
- timezone.get_current_timezone())
+ datetime.datetime(date.year, date.month, date.day), timezone.get_current_timezone()
+ )
+
def queryset_fixpoint(initial, qs_function):
initial = set(initial)
@@ -104,7 +109,7 @@ def a2_wscall(url, method, json=None):
'url': url,
'auth': requests.auth.HTTPBasicAuth(
app_settings.settings.AUTHENTIC_USER, app_settings.settings.AUTHENTIC_PASSWORD
- )
+ ),
}
if json:
kwargs['json'] = json
diff --git a/docbow_project/docbow/validators.py b/docbow_project/docbow/validators.py
index 99f41ee..f8acc58 100644
--- a/docbow_project/docbow/validators.py
+++ b/docbow_project/docbow/validators.py
@@ -5,7 +5,7 @@ from django.core.validators import RegexValidator
validate_phone = RegexValidator('^\+\d+$')
validate_fr_be_phone = RegexValidator('^\+(?:33[67]\d{8}|324\d{8})$')
+
def phone_normalize(phone_number):
'''Remove usual separators from phone number.'''
return re.sub('[\.\-\s]', '', phone_number)
-
diff --git a/docbow_project/docbow/views.py b/docbow_project/docbow/views.py
index 56d64c7..d7019cd 100644
--- a/docbow_project/docbow/views.py
+++ b/docbow_project/docbow/views.py
@@ -13,9 +13,7 @@ import django.contrib.auth as auth
from django.shortcuts import render, redirect, get_object_or_404
from django.conf import settings
from django.urls import reverse
-from django.http import (
- HttpResponse, HttpResponseForbidden, HttpResponseRedirect, Http404, JsonResponse
-)
+from django.http import HttpResponse, HttpResponseForbidden, HttpResponseRedirect, Http404, JsonResponse
from django.db.models.expressions import RawSQL
from django.db.models.query import Q
from django.contrib.auth.models import User
@@ -41,11 +39,23 @@ import watson.search as watson
from docbow_project.docbow.forms import (
- FileForm, AnonymousContactForm, ContactForm, ForwardingForm, FilterForm
+ FileForm,
+ AnonymousContactForm,
+ ContactForm,
+ ForwardingForm,
+ FilterForm,
)
from docbow_project.docbow.models import (
- Mailbox, AttachedFile, SendingLimitation, MailingList, is_guest, Document, FileType,
- DeletedDocument, SeenDocument, non_guest_users
+ Mailbox,
+ AttachedFile,
+ SendingLimitation,
+ MailingList,
+ is_guest,
+ Document,
+ FileType,
+ DeletedDocument,
+ SeenDocument,
+ non_guest_users,
)
from docbow_project.docbow.decorators import as_delegate
from docbow_project.docbow import tables
@@ -58,14 +68,14 @@ from docbow_project.docbow.utils import date_to_aware_datetime
gettext_noop = lambda x: x
+
@login_required
def homepage(request):
response = redirect('inbox')
server_name = request.META.get('SERVER_NAME')
if server_name.count('.') >= 2:
domain = '.' + '.'.join(server_name.split('.')[-2:])
- response.set_cookie('docbow-user', 'true', domain=domain,
- max_age=30*86400)
+ response.set_cookie('docbow-user', 'true', domain=domain, max_age=30 * 86400)
return response
@@ -84,12 +94,13 @@ def get_document(request, mailbox_id, outbox):
private_filter = Q(private=False) | Q(private=True, mailboxes__owner=request.user)
if hasattr(request.user, 'delegate'):
private_filter = Q(private=False)
- return Document.objects \
- .exclude(deleteddocument__user=request.user, deleteddocument__soft_delete=False) \
- .filter(id=mailbox_id, mailboxes__in=mailboxes) \
- .filter(private_filter) \
- .distinct() \
+ return (
+ Document.objects.exclude(deleteddocument__user=request.user, deleteddocument__soft_delete=False)
+ .filter(id=mailbox_id, mailboxes__in=mailboxes)
+ .filter(private_filter)
+ .distinct()
.get()
+ )
class Row(object):
@@ -100,6 +111,7 @@ class Row(object):
def user_mailing_list_names(user):
return user.mailing_lists.values_list('name', flat=True)
+
def recursive_lists(lists):
lists = set(lists)
while True:
@@ -109,32 +121,32 @@ def recursive_lists(lists):
break
return lists
+
def get_file_form_kwargs(request):
user = request.user
if is_guest(user):
user = user.delegations_by.get().by
delegators = []
else:
- delegators = non_guest_users().filter(
- Q(id=user.id) |
- Q(delegations_to__to=user)) \
- .distinct()
+ delegators = non_guest_users().filter(Q(id=user.id) | Q(delegations_to__to=user)).distinct()
user_lists = MailingList.objects.is_member_of(user)
- own_limitations = MailingList.objects \
- .filter(is_active=True) \
- .filter(lists_limitation__mailing_list__in=user_lists) \
- .distinct() \
- .order_by('name')
+ own_limitations = (
+ MailingList.objects.filter(is_active=True)
+ .filter(lists_limitation__mailing_list__in=user_lists)
+ .distinct()
+ .order_by('name')
+ )
if not own_limitations:
return {}
kwargs = {}
user_lists = MailingList.objects.are_member_of([user] + list(delegators))
if SendingLimitation.objects.filter(mailing_list__in=user_lists):
- lists = MailingList.objects \
- .filter(is_active=True) \
- .filter(lists_limitation__mailing_list__in=user_lists) \
- .distinct() \
- .order_by('name')
+ lists = (
+ MailingList.objects.filter(is_active=True)
+ .filter(lists_limitation__mailing_list__in=user_lists)
+ .distinct()
+ .order_by('name')
+ )
lists = recursive_lists(lists)
users = non_guest_users().filter(mailing_lists__in=lists).distinct()
if lists:
@@ -149,24 +161,23 @@ def get_filetype_limitation(user):
user = user.delegations_by.get().by
delegators = []
else:
- delegators = non_guest_users().filter(
- Q(id=user.id) |
- Q(delegations_to__to=user)) \
- .distinct()
+ delegators = non_guest_users().filter(Q(id=user.id) | Q(delegations_to__to=user)).distinct()
# if user has basically no limitation, do not limit him
user_lists = MailingList.objects.is_member_of(user)
- own_limitations = FileType.objects \
- .filter(is_active=True, filetype_limitation__mailing_list__in=user_lists) \
- .distinct() \
- .order_by('name')
+ own_limitations = (
+ FileType.objects.filter(is_active=True, filetype_limitation__mailing_list__in=user_lists)
+ .distinct()
+ .order_by('name')
+ )
if not own_limitations.exists():
return FileType.objects.none()
if delegators:
user_lists = MailingList.objects.are_member_of([user] + list(delegators))
- return FileType.objects \
- .filter(is_active=True, filetype_limitation__mailing_list__in=user_lists) \
- .distinct() \
- .order_by('name')
+ return (
+ FileType.objects.filter(is_active=True, filetype_limitation__mailing_list__in=user_lists)
+ .distinct()
+ .order_by('name')
+ )
else:
return own_limitations
@@ -179,18 +190,18 @@ def send_file(request, file_type_id):
try:
reply_to = get_document(request, request.GET['reply_to'], False)
except Document.DoesNotExist:
- raise Http404
+ raise Http404
except KeyError:
reply_to = None
if hasattr(request.user, 'delegate'):
delegators = User.objects.none()
else:
- delegators = User.objects.filter(
- Q(id=request.user.id) |
- Q(delegations_to__to=request.user)) \
- .filter(is_active=True) \
- .order_by('last_name', 'first_name', 'username') \
- .distinct()
+ delegators = (
+ User.objects.filter(Q(id=request.user.id) | Q(delegations_to__to=request.user))
+ .filter(is_active=True)
+ .order_by('last_name', 'first_name', 'username')
+ .distinct()
+ )
real_user = getattr(request.user, 'delegate', request.user)
limitations = get_filetype_limitation(request.user)
if limitations:
@@ -199,11 +210,16 @@ def send_file(request, file_type_id):
if request.method == 'POST':
if 'send' not in request.POST:
return redirect('outbox')
- form = FileForm(request.POST, request.FILES,
- default_sender=request.user, user=real_user,
- delegations=delegators, reply_to=reply_to,
- file_type=file_type,
- **get_file_form_kwargs(request))
+ form = FileForm(
+ request.POST,
+ request.FILES,
+ default_sender=request.user,
+ user=real_user,
+ delegations=delegators,
+ reply_to=reply_to,
+ file_type=file_type,
+ **get_file_form_kwargs(request),
+ )
try:
if form.is_valid():
new_send = form.save(commit=False)
@@ -221,37 +237,52 @@ def send_file(request, file_type_id):
new_send.to_user.set(to_user)
new_send.to_list.set(to_list)
recipients_count = new_send.post()
- request.record('create-document', 'sent document {document} '
- 'delivered to {recipients_count}', document=new_send,
- recipients_count=recipients_count)
+ request.record(
+ 'create-document',
+ 'sent document {document} ' 'delivered to {recipients_count}',
+ document=new_send,
+ recipients_count=recipients_count,
+ )
return redirect('outbox')
except Exception:
import logging
logging.getLogger(__name__).exception('unable to create a new document')
- form._errors.setdefault(NON_FIELD_ERRORS, form.error_class()) \
- .append(_('An internal error occured, administrators '
+ form._errors.setdefault(NON_FIELD_ERRORS, form.error_class()).append(
+ _(
+ 'An internal error occured, administrators '
'have been notified; sending seems blocked at the moment. You should '
'try agrain later. If it still does not work then, contact '
- 'your administrator.'))
+ 'your administrator.'
+ )
+ )
else:
- form = FileForm(default_sender=request.user, user=real_user,
- delegations=delegators, reply_to=reply_to,
- file_type=file_type,
- **get_file_form_kwargs(request))
+ form = FileForm(
+ default_sender=request.user,
+ user=real_user,
+ delegations=delegators,
+ reply_to=reply_to,
+ file_type=file_type,
+ **get_file_form_kwargs(request),
+ )
form_action = ''
if reply_to:
form_action = '?reply_to=%s' % reply_to.id
return render(
- request, 'docbow/send_file.html',
+ request,
+ 'docbow/send_file.html',
{
- 'form': form, 'view_name': 'send-file', 'reply_to': reply_to,
- 'url': request.GET.get('url'), 'form_action': form_action
- }
+ 'form': form,
+ 'view_name': 'send-file',
+ 'reply_to': reply_to,
+ 'url': request.GET.get('url'),
+ 'form_action': form_action,
+ },
)
+
@never_cache
def upload(request, attached_file):
response = HttpResponse(attached_file.content.chunks(), content_type='application/octet-stream')
@@ -277,10 +308,13 @@ def message_attached_file(request, mailbox_id, attached_file, outbox=False):
before, otherwise return 404.
'''
document = get_document_and_mark_seen(request, mailbox_id, outbox)
- attached_file = get_object_or_404(AttachedFile, document=document,
- pk=attached_file)
- request.record('download', 'download attached file {attached_file} of document {document}',
- attached_file=attached_file, document=document)
+ attached_file = get_object_or_404(AttachedFile, document=document, pk=attached_file)
+ request.record(
+ 'download',
+ 'download attached file {attached_file} of document {document}',
+ attached_file=attached_file,
+ document=document,
+ )
return upload(request, attached_file)
@@ -323,11 +357,9 @@ def message(request, mailbox_id, outbox=False):
document = get_document(request, mailbox_id, outbox)
except Document.DoesNotExist:
if Document.objects.filter(pk=mailbox_id):
- messages.warning(request,
- _('You cannot see this document as you are not the recipient'))
+ messages.warning(request, _('You cannot see this document as you are not the recipient'))
else:
- messages.warning(request,
- _('Document not found'))
+ messages.warning(request, _('Document not found'))
if outbox:
return redirect('outbox')
else:
@@ -337,31 +369,32 @@ def message(request, mailbox_id, outbox=False):
else:
back_pair = (reverse('inbox'), gettext_noop('back to inbox'))
back = 'outbox' if outbox else 'inbox'
- ctx = { 'outbox': outbox, 'document': document,
- 'view_name': back, 'back': back_pair }
+ ctx = {'outbox': outbox, 'document': document, 'view_name': back, 'back': back_pair}
if not outbox:
limitations = get_filetype_limitation(request.user)
if not limitations or limitations.filter(id=document.filetype.id).exists():
if request.method == 'POST':
- form = ForwardingForm(request.POST, user=request.user,
- **get_file_form_kwargs(request))
+ form = ForwardingForm(request.POST, user=request.user, **get_file_form_kwargs(request))
if form.is_valid():
users, lists = form_to_user_and_list(form)
recipients_count, forwarded_document = document.forward(
- form.cleaned_data['sender'], lists, users)
- request.record('forward-document', 'forwarded document '
- '{document} as new document {new_document}',
- document=forwarded_document.from_document,
- new_document=forwarded_document.to_document)
- msg = ungettext('Document forwarded to {recipients_count} '
- 'recipient.', 'Document forwarded to {recipients_count} '
- 'recipients.', recipients_count) \
- .format(recipients_count=recipients_count)
+ form.cleaned_data['sender'], lists, users
+ )
+ request.record(
+ 'forward-document',
+ 'forwarded document ' '{document} as new document {new_document}',
+ document=forwarded_document.from_document,
+ new_document=forwarded_document.to_document,
+ )
+ msg = ungettext(
+ 'Document forwarded to {recipients_count} ' 'recipient.',
+ 'Document forwarded to {recipients_count} ' 'recipients.',
+ recipients_count,
+ ).format(recipients_count=recipients_count)
messages.info(request, msg)
return redirect('inbox-message', mailbox_id=document.pk)
else:
- form = ForwardingForm(user=request.user,
- **get_file_form_kwargs(request))
+ form = ForwardingForm(user=request.user, **get_file_form_kwargs(request))
ctx['form'] = form
ctx['attached_files'] = attached_files = []
for attached_file in document.attached_files.order_by('kind__position', 'kind__name', 'id'):
@@ -369,11 +402,11 @@ def message(request, mailbox_id, outbox=False):
attached_files[-1][1].append(attached_file)
else:
attached_files.append((attached_file.kind, [attached_file]))
- request.record('message-view', 'looked at document {document}',
- document=document)
+ request.record('message-view', 'looked at document {document}', document=document)
ctx['related_users'] = get_related_users(request)
return render(request, 'docbow/message.html', ctx)
+
def get_help_content(pagename):
filepath = os.path.join(settings.HELP_DIR, pagename)
parsed_doc = BeautifulSoup(open(filepath).read())
@@ -391,12 +424,13 @@ def get_help_content(pagename):
t.name = 'h3'
return force_text(page)
+
@login_required
def help(request, pagename='index.html'):
if pagename.endswith('.html'):
- return render(request, 'docbow/help.html', {
- 'view_name': 'help',
- 'content': get_help_content(pagename) })
+ return render(
+ request, 'docbow/help.html', {'view_name': 'help', 'content': get_help_content(pagename)}
+ )
else:
filepath = os.path.join(settings.HELP_DIR, pagename)
if not os.path.abspath(filepath).startswith(settings.HELP_DIR):
@@ -405,16 +439,15 @@ def help(request, pagename='index.html'):
response['Content-Type'] = 'image/png'
return response
-def contact(request, template='docbow/contact.html',
- form_class=AnonymousContactForm):
+
+def contact(request, template='docbow/contact.html', form_class=AnonymousContactForm):
user = request.user
if user.is_authenticated:
template = 'docbow/contact_user.html'
form_class = ContactForm
contacts = User.objects.filter(groups__name__in=settings.CONTACT_GROUPS)
if not bool(contacts):
- msg = N_('unable to send the contact mail because there is no '
- 'administrator group to receive them')
+ msg = N_('unable to send the contact mail because there is no ' 'administrator group to receive them')
request.error_record('error', msg)
messages.error(request, _(msg))
return redirect('inbox')
@@ -422,13 +455,15 @@ def contact(request, template='docbow/contact.html',
form = form_class(request.POST)
if form.is_valid():
cleaned_data = form.cleaned_data
- to = [ contact.email for contact in contacts ]
+ to = [contact.email for contact in contacts]
subject = settings.CONTACT_SUBJECT_PREFIX + cleaned_data['subject']
message = cleaned_data['message']
if user.is_authenticated:
reply_to = user.email
- body = _('Message from %(name)s <%(email)s>') % { 'name':
- user.get_full_name(), 'email': reply_to } + '\n\n%s' % message
+ body = (
+ _('Message from %(name)s <%(email)s>') % {'name': user.get_full_name(), 'email': reply_to}
+ + '\n\n%s' % message
+ )
else:
reply_to = cleaned_data['email']
body = _('Message from %(name)s <%(email)s>') % cleaned_data
@@ -436,36 +471,43 @@ def contact(request, template='docbow/contact.html',
body += _('\nPhone number: %s') % cleaned_data['phone_number']
body += '\n\n%s' % message
try:
- EmailMessage(to=to, subject=subject, body=body,
- headers={'Reply-To': reply_to}).send()
+ EmailMessage(to=to, subject=subject, body=body, headers={'Reply-To': reply_to}).send()
messages.info(request, _('Your message was sent to %d administrators') % len(to))
- request.record('contact', 'sent mail to administrators with '
- 'subject "{subject}" and message "{message}", reply should be sent to email '
- '{reply_to} or phone number "{phone}"',
- subject=subject,
- message=message,
- reply_to=reply_to,
- phone=cleaned_data.get('phone_number'))
+ request.record(
+ 'contact',
+ 'sent mail to administrators with '
+ 'subject "{subject}" and message "{message}", reply should be sent to email '
+ '{reply_to} or phone number "{phone}"',
+ subject=subject,
+ message=message,
+ reply_to=reply_to,
+ phone=cleaned_data.get('phone_number'),
+ )
except (smtplib.SMTPException, socket.error):
import logging
logging.getLogger(__name__).exception('unable to send mail to administrators')
- request.error_record('error', 'unable to send mail to administrators with '
- 'subject "{subject}" and message "{message}", reply should be sent to email '
- '{reply_to} or phone number "{phone}"',
- subject=subject,
- message=message,
- reply_to=reply_to,
- phone=cleaned_data.get('phone_number'))
+ request.error_record(
+ 'error',
+ 'unable to send mail to administrators with '
+ 'subject "{subject}" and message "{message}", reply should be sent to email '
+ '{reply_to} or phone number "{phone}"',
+ subject=subject,
+ message=message,
+ reply_to=reply_to,
+ phone=cleaned_data.get('phone_number'),
+ )
return redirect('inbox')
else:
form = form_class()
- return render(request, template, { 'form': form, 'view_name': 'contact' })
+ return render(request, template, {'form': form, 'view_name': 'contact'})
+
def logout(request):
auth.logout(request)
return redirect('inbox')
+
@login_required
@never_cache
def delete(request, mailbox_id, outbox=False):
@@ -473,24 +515,22 @@ def delete(request, mailbox_id, outbox=False):
page = request.GET.get('page', 1)
back = 'outbox' if outbox else 'inbox'
viewname = back + '-message-delete'
- back_pair = ('%s?page=%s' % (reverse(back), page),
- gettext_noop('back to %s' % back))
+ back_pair = ('%s?page=%s' % (reverse(back), page), gettext_noop('back to %s' % back))
try:
document = get_document(request, mailbox_id, outbox)
except Document.DoesNotExist:
return redirect(back_pair[0])
if request.method == 'GET':
- return render(request, 'docbow/delete.html', { 'document': document, 'back': back_pair, 'view_name': viewname })
+ return render(
+ request, 'docbow/delete.html', {'document': document, 'back': back_pair, 'view_name': viewname}
+ )
else:
try:
DeletedDocument.objects.get(user=request.user, document=document)
except DeletedDocument.DoesNotExist:
DeletedDocument.objects.create(
- user=request.user,
- document=document,
- soft_delete=True,
- soft_delete_date=now()
+ user=request.user, document=document, soft_delete=True, soft_delete_date=now()
)
request.record('delete-document', 'marked document {document} as deleted', document=document)
@@ -504,9 +544,7 @@ def inbox_by_document(request, document_id):
@require_http_methods(["POST"])
def restore(request, doc_id, outbox=False):
try:
- deleted_doc = DeletedDocument.objects.get(
- user=request.user, document__pk=doc_id, soft_delete=True
- )
+ deleted_doc = DeletedDocument.objects.get(user=request.user, document__pk=doc_id, soft_delete=True)
deleted_doc.delete()
except DeletedDocument.DoesNotExist:
pass
@@ -531,7 +569,9 @@ def su(request, username, redirect_url='/'):
real_user = User.objects.get(username=real_username)
pair_id = '%s,%s' % (real_user.id, su_user.id)
request.session[SESSION_KEY] = pair_id
- request.session[BACKEND_SESSION_KEY] = 'docbow_project.docbow.auth_backend.DelegationAuthBackend'
+ request.session[
+ BACKEND_SESSION_KEY
+ ] = 'docbow_project.docbow.auth_backend.DelegationAuthBackend'
request.session['has_superuser_power'] = True
else:
request.session[SESSION_KEY] = su_user.id
@@ -541,12 +581,17 @@ def su(request, username, redirect_url='/'):
else:
return http.HttpResponseRedirect('/')
+
@login_required
@never_cache
def mailing_lists(request, template='docbow/mailing-lists.html'):
- mailing_lists = MailingList.objects.active().filter(Q(members__isnull=False) |
- Q(mailing_list_members__isnull=False)).distinct().order_by('name')
- return render(request, template, { 'mailing_lists': mailing_lists })
+ mailing_lists = (
+ MailingList.objects.active()
+ .filter(Q(members__isnull=False) | Q(mailing_list_members__isnull=False))
+ .distinct()
+ .order_by('name')
+ )
+ return render(request, template, {'mailing_lists': mailing_lists})
def robots(request):
@@ -567,8 +612,7 @@ class DateFilterMixinView(object):
if 'clear' in self.request.GET:
form = FilterForm(request=self.request, outbox=self.outbox)
else:
- form = FilterForm(data=self.request.GET,
- request=self.request, outbox=self.outbox)
+ form = FilterForm(data=self.request.GET, request=self.request, outbox=self.outbox)
self._form = form
return self._form
@@ -592,7 +636,9 @@ class DateFilterMixinView(object):
not_after = date_to_aware_datetime(not_after)
qs = qs.filter(date__lt=not_after)
if search_terms:
- objects_ids = watson.search(search_terms, models=(Document,)).values_list('object_id_int', flat=True)
+ objects_ids = watson.search(search_terms, models=(Document,)).values_list(
+ 'object_id_int', flat=True
+ )
qs = qs.filter(id__in=objects_ids)
return qs
@@ -605,6 +651,7 @@ class ExtraContextMixin(object):
context.update(self.extra_ctx)
return context
+
def get_related_users(request):
'''Compute the list of users for which we can see the mailboxes, and cache
it in the session.
@@ -618,6 +665,7 @@ def get_related_users(request):
request.session['related_users'] = [user.pk for user in users]
return User.objects.filter(pk__in=request.session['related_users'])
+
class MailboxQuerysetMixin(object):
def get_queryset(self):
qs = super(MailboxQuerysetMixin, self).get_queryset()
@@ -655,7 +703,7 @@ class MailboxView(ExtraContextMixin, MailboxQuerysetMixin, tables_views.SingleTa
model = Document
table_class = tables.MailboxTable
table_pagination = {
- 'per_page': app_settings.DOCBOW_MAILBOX_PER_PAGE,
+ 'per_page': app_settings.DOCBOW_MAILBOX_PER_PAGE,
}
def get_context_data(self):
@@ -668,7 +716,7 @@ class TrashMailboxView(ExtraContextMixin, TrashMailboxQuerysetMixin, tables_view
model = Document
table_class = tables.MailboxTable
table_pagination = {
- 'per_page': app_settings.DOCBOW_MAILBOX_PER_PAGE,
+ 'per_page': app_settings.DOCBOW_MAILBOX_PER_PAGE,
}
@@ -677,7 +725,7 @@ class CSVMultipleObjectMixin(object):
filename = ''
def get_header(self):
- return [ column['caption'] for column in self.mapping ]
+ return [column['caption'] for column in self.mapping]
def get_cell(self, mailbox, attribute):
value = operator.attrgetter(attribute)(mailbox)
@@ -708,6 +756,7 @@ class ODSMultipleObjectMixin(CSVMultipleObjectMixin):
def get(self, request, *args, **kwargs):
from . import ods
+
response = HttpResponse(content_type='application/vnd.oasis.opendocument.spreadsheet')
response['Content-Disposition'] = 'attachment; filename="%s"' % self.filename
workbook = ods.Workbook(encoding='utf-8')
@@ -720,18 +769,21 @@ class ODSMultipleObjectMixin(CSVMultipleObjectMixin):
return response
-class CSVMailboxView(CSVMultipleObjectMixin, ExtraContextMixin,
- MailboxQuerysetMixin, MultipleObjectMixin,
- tables_views.SingleTableMixin, View):
+class CSVMailboxView(
+ CSVMultipleObjectMixin,
+ ExtraContextMixin,
+ MailboxQuerysetMixin,
+ MultipleObjectMixin,
+ tables_views.SingleTableMixin,
+ View,
+):
model = Document
-
@property
def filename(self):
return '{prefix}-{user}-{date}.csv'.format(
- prefix=self.filename_prefix,
- user=self.request.user,
- date=datetime.date.today())
+ prefix=self.filename_prefix, user=self.request.user, date=datetime.date.today()
+ )
def get_header(self):
table = self.get_table()
@@ -752,9 +804,8 @@ class ODSMailboxView(ODSMultipleObjectMixin, CSVMailboxView):
@property
def filename(self):
return '{prefix}-{user}-{date}.ods'.format(
- prefix=self.filename_prefix,
- user=self.request.user,
- date=datetime.date.today())
+ prefix=self.filename_prefix, user=self.request.user, date=datetime.date.today()
+ )
class CSVInboxView(CSVMailboxView):
@@ -788,6 +839,7 @@ class ODSOutboxView(ODSMailboxView, CSVOutboxView):
outbox_ods = ODSOutboxView.as_view()
+
class DeleteDocumentsView(object):
def post(self, request, *args, **kwargs):
documents = None
@@ -804,22 +856,21 @@ class DeleteDocumentsView(object):
documents = documents.exclude(deleteddocument__user=request.user)
dd = [
DeletedDocument(
- user=request.user,
- document=document,
- soft_delete=True,
- soft_delete_date=now()
- ) for document in documents
+ user=request.user, document=document, soft_delete=True, soft_delete_date=now()
+ )
+ for document in documents
]
DeletedDocument.objects.bulk_create(dd)
return HttpResponseRedirect(request.build_absolute_uri())
+
class InboxView(DeleteDocumentsView, DateFilterMixinView, MailboxView):
http_method_names = ['get', 'post']
outbox = False
table_class = tables.InboxTable
template_name = 'docbow/inbox_list.html'
extra_ctx = {
- 'view_name': 'inbox',
+ 'view_name': 'inbox',
}
def get_context_data(self):
@@ -836,7 +887,7 @@ class InboxTrashView(TrashMailboxView):
table_class = tables.InboxTrashTable
template_name = 'docbow/inbox_trash_list.html'
extra_ctx = {
- 'view_name': 'inbox_trash',
+ 'view_name': 'inbox_trash',
}
@@ -848,7 +899,7 @@ class OutboxView(DeleteDocumentsView, DateFilterMixinView, MailboxView):
table_class = tables.OutboxTable
template_name = 'docbow/outbox_list.html'
extra_ctx = {
- 'view_name': 'outbox',
+ 'view_name': 'outbox',
}
def get_context_data(self):
@@ -865,15 +916,13 @@ class OutboxTrashView(TrashMailboxView):
table_class = tables.OutboxTrashTable
template_name = 'docbow/outbox_trash_list.html'
extra_ctx = {
- 'view_name': 'outbox_trash',
+ 'view_name': 'outbox_trash',
}
outbox_trash_view = login_required(OutboxTrashView.as_view())
-
-
class SendFileSelectorView(ListView):
template_name = 'docbow/send_file_selector.html'
model = FileType
@@ -892,7 +941,9 @@ send_file_selector = login_required(SendFileSelectorView.as_view())
delegate = RedirectView.as_view(url='/profile/', permanent=False)
-password_change = sensitive_post_parameters()(never_cache(login_required(as_delegate(profile_views.PasswordChangeView.as_view()))))
+password_change = sensitive_post_parameters()(
+ never_cache(login_required(as_delegate(profile_views.PasswordChangeView.as_view())))
+)
profile = login_required(as_delegate(profile_views.FullProfileView.as_view()))
@@ -901,16 +952,11 @@ profile = login_required(as_delegate(profile_views.FullProfileView.as_view()))
def search_terms(request, outbox=True, limit_choices=10):
q = request.GET.get('term', '')
- documents = sql.get_documents(
- Document.objects.all(),
- get_related_users(request), request.user, outbox,
- )
+ documents = sql.get_documents(Document.objects.all(), get_related_users(request), request.user, outbox,)
search = watson.search(q, models=(documents,))
choices = []
for match in search:
- match_words = [
- word for word in match.description.split() if word.lower().startswith(q.lower())
- ]
+ match_words = [word for word in match.description.split() if word.lower().startswith(q.lower())]
for word in match_words:
if word in choices:
continue
diff --git a/docbow_project/docbow/widgets.py b/docbow_project/docbow/widgets.py
index df8d092..404e2d1 100644
--- a/docbow_project/docbow/widgets.py
+++ b/docbow_project/docbow/widgets.py
@@ -1,8 +1,7 @@
import uuid
import re
-from django.forms import Textarea, MultiWidget, Select, \
- HiddenInput, FileInput, SelectMultiple
+from django.forms import Textarea, MultiWidget, Select, HiddenInput, FileInput, SelectMultiple
from django.utils.safestring import mark_safe
from django.conf import settings
from django.template.loader import render_to_string
@@ -27,8 +26,7 @@ class TextInpuWithPredefinedValues(MultiWidget):
'''
def __init__(self, attrs=None, choices=[]):
- widget_list = (Select(attrs=attrs, choices=choices),
- Textarea(attrs=attrs))
+ widget_list = (Select(attrs=attrs, choices=choices), Textarea(attrs=attrs))
super(TextInpuWithPredefinedValues, self).__init__(widget_list, attrs)
def decompress(self, value):
@@ -42,14 +40,15 @@ class TextInpuWithPredefinedValues(MultiWidget):
return select
def render(self, name, value, attrs=None, renderer=None):
- output = super(TextInpuWithPredefinedValues, self).render(name, value,
- attrs)
- return output + mark_safe(self.CLIENT_CODE % { 'name': name })
+ output = super(TextInpuWithPredefinedValues, self).render(name, value, attrs)
+ return output + mark_safe(self.CLIENT_CODE % {'name': name})
+
class MultiFileInput(FileInput):
'''
FileInput field supporting the multiple attribute
'''
+
def __init__(self, attrs=None):
super(MultiFileInput, self).__init__(attrs)
self.attrs['multiple'] = 'true'
@@ -60,20 +59,22 @@ class MultiFileInput(FileInput):
else:
return []
+
class JqueryFileUploadFileInput(MultiFileInput):
template_name = 'docbow/upload-multiwidget.html'
class Media:
- js = ('jquery-ui/js/jquery-ui-1.8.4.min.js',
- 'jquery-plugin/js/jquery.tmpl.min-beta1.js',
- 'jquery-plugin/js/jquery.iframe-transport.js',
- 'jquery-plugin/js/jquery.fileupload.js',
- 'jquery-plugin/js/jquery.fileupload-ui.js')
- css = {'all': ('jquery-ui/css/jquery-ui-1.8.4.css',
- 'jquery-plugin/css/jquery.fileupload-ui.css',)}
+ js = (
+ 'jquery-ui/js/jquery-ui-1.8.4.min.js',
+ 'jquery-plugin/js/jquery.tmpl.min-beta1.js',
+ 'jquery-plugin/js/jquery.iframe-transport.js',
+ 'jquery-plugin/js/jquery.fileupload.js',
+ 'jquery-plugin/js/jquery.fileupload-ui.js',
+ )
+ css = {'all': ('jquery-ui/css/jquery-ui-1.8.4.css', 'jquery-plugin/css/jquery.fileupload-ui.css',)}
- def __init__(self, extensions=[], attached_file_kind=None, *args,**kwargs):
+ def __init__(self, extensions=[], attached_file_kind=None, *args, **kwargs):
self.extensions = extensions
self.attached_file_kind = attached_file_kind
super(JqueryFileUploadFileInput, self).__init__(*args, **kwargs)
@@ -88,7 +89,7 @@ class JqueryFileUploadFileInput(MultiFileInput):
'attached_file_kind': self.attached_file_kind,
'files': self.files,
'name': name,
- 'STATIC_URL': settings.STATIC_URL
+ 'STATIC_URL': settings.STATIC_URL,
}
def get_context(self, name, value, attrs):
@@ -111,14 +112,18 @@ class JqueryFileUploadInput(MultiWidget):
upload_id = None
template_name = 'docbow/multiwidget.html'
-
- def __init__(self, attrs=None, choices=[], max_filename_length=None, extensions=[], attached_file_kind=None):
+ def __init__(
+ self, attrs=None, choices=[], max_filename_length=None, extensions=[], attached_file_kind=None
+ ):
self.extensions = extensions
self.max_filename_length = max_filename_length
self.attached_file_kind = attached_file_kind
- widget_list = (HiddenInput(attrs=attrs),
- JqueryFileUploadFileInput(attrs=attrs, extensions=extensions,
- attached_file_kind=attached_file_kind))
+ widget_list = (
+ HiddenInput(attrs=attrs),
+ JqueryFileUploadFileInput(
+ attrs=attrs, extensions=extensions, attached_file_kind=attached_file_kind
+ ),
+ )
super(JqueryFileUploadInput, self).__init__(widget_list, attrs)
def decompress(self, value):
@@ -158,11 +163,12 @@ class JqueryFileUploadInput(MultiWidget):
url += 'max_filename_length=%d' % self.max_filename_length
self.widgets[1].url = url
self.widgets[1].files = '/upload/%s/' % get_files_for_id(self.upload_id)
- output = super(JqueryFileUploadInput, self).render(name, value,
- attrs)
+ output = super(JqueryFileUploadInput, self).render(name, value, attrs)
fileinput_id = '%s_%s' % (attrs['id'], '1')
- return output + mark_safe(self.CLIENT_CODE % {
- 'upload_id': self.upload_id, 'fileinput_id': fileinput_id })
+ return output + mark_safe(
+ self.CLIENT_CODE % {'upload_id': self.upload_id, 'fileinput_id': fileinput_id}
+ )
+
class ForcedValueWidget(SelectMultiple):
def __init__(self, attrs=None, format=None, value=None, display_value=""):
@@ -174,7 +180,9 @@ class ForcedValueWidget(SelectMultiple):
return self.value
def render(self, name, value, attrs=None, renderer=None):
- return mark_safe(u'%s
' % self.display_value)
+ return mark_safe(
+ u'%s
' % self.display_value
+ )
class FilteredSelectMultiple(SelectMultiple):
@@ -185,12 +193,15 @@ class FilteredSelectMultiple(SelectMultiple):
Note that the resulting JavaScript assumes that the jsi18n
catalog has been loaded in the page
"""
+
class Media:
- js = ("docbow/filter-widget/js/core.js",
- "docbow/filter-widget/js/SelectBox.js",
- "docbow/filter-widget/js/SelectFilter2.js",
- "js/i18n.js")
- css = { 'all': ('docbow/filter-widget/css/filter-widget.css',)}
+ js = (
+ "docbow/filter-widget/js/core.js",
+ "docbow/filter-widget/js/SelectBox.js",
+ "docbow/filter-widget/js/SelectFilter2.js",
+ "js/i18n.js",
+ )
+ css = {'all': ('docbow/filter-widget/css/filter-widget.css',)}
def __init__(self, verbose_name, is_stacked, attrs=None, choices=()):
self.verbose_name = verbose_name
@@ -198,9 +209,11 @@ class FilteredSelectMultiple(SelectMultiple):
super(FilteredSelectMultiple, self).__init__(attrs, choices)
def render(self, name, value, attrs=None, *args, **kwargs):
- if attrs is None: attrs = {}
+ if attrs is None:
+ attrs = {}
attrs['class'] = 'selectfilter'
- if self.is_stacked: attrs['class'] += 'stacked'
+ if self.is_stacked:
+ attrs['class'] += 'stacked'
# disable html5 validation
if 'required' in attrs:
@@ -210,8 +223,10 @@ class FilteredSelectMultiple(SelectMultiple):
output.append(u'\n' % \
- (name, self.verbose_name.replace('"', '\\"'), int(self.is_stacked), settings.STATIC_URL))
+ output.append(
+ u'SelectFilter.init("id_%s", "%s", %s, "%s"); });\n'
+ % (name, self.verbose_name.replace('"', '\\"'), int(self.is_stacked), settings.STATIC_URL)
+ )
return mark_safe(u''.join(output))
diff --git a/docbow_project/humantime/templatetags/humantime.py b/docbow_project/humantime/templatetags/humantime.py
index 711158a..79786d5 100644
--- a/docbow_project/humantime/templatetags/humantime.py
+++ b/docbow_project/humantime/templatetags/humantime.py
@@ -8,18 +8,19 @@ from .. import utils
register = template.Library()
+
@register.filter
def humandate(dt):
full_dt = date(dt, 'SHORT_DATE_FORMAT')
- s = u'{1}'.format(
- escape(full_dt), escape(utils.datetime2human(dt)))
+ s = u'{1}'.format(escape(full_dt), escape(utils.datetime2human(dt)))
return mark_safe(s)
+
@register.filter
def humantime(dt):
dt = localtime(dt)
full_dt = date(dt, 'SHORT_DATETIME_FORMAT')
s = u'{1}'.format(
- escape(full_dt), escape(utils.datetime2human(dt, include_time=True)))
+ escape(full_dt), escape(utils.datetime2human(dt, include_time=True))
+ )
return mark_safe(s)
-
diff --git a/docbow_project/humantime/utils.py b/docbow_project/humantime/utils.py
index fcc7583..2b60e7e 100644
--- a/docbow_project/humantime/utils.py
+++ b/docbow_project/humantime/utils.py
@@ -4,14 +4,14 @@ from django.utils.translation import pgettext
from django.utils.timezone import localtime, get_default_timezone
from django.template.defaultfilters import date
+
def datetime2human(dt, include_time=False, days_limit=7):
'''Format a datetime object for human consumption'''
if isinstance(dt, datetime.datetime):
dt = localtime(dt)
time = dt.strftime('%H:%M')
else:
- dt = datetime.datetime(year=dt.year, month=dt.month, day=dt.day,
- tzinfo=get_default_timezone())
+ dt = datetime.datetime(year=dt.year, month=dt.month, day=dt.day, tzinfo=get_default_timezone())
dt = localtime(dt)
include_time = False
today = datetime.date.today()
diff --git a/docbow_project/pfwb/admin.py b/docbow_project/pfwb/admin.py
index 83544ed..da88cfd 100644
--- a/docbow_project/pfwb/admin.py
+++ b/docbow_project/pfwb/admin.py
@@ -8,7 +8,8 @@ class PloneFileTypeInlineAdmin(admin.StackedInline):
model = models.PloneFileType
extra = 0
+
if getattr(docbow_admin.FileTypeAdmin, 'inlines'):
- docbow_admin.FileTypeAdmin.inlines += [ PloneFileTypeInlineAdmin ]
+ docbow_admin.FileTypeAdmin.inlines += [PloneFileTypeInlineAdmin]
else:
- docbow_admin.FileTypeAdmin.inlines = [ PloneFileTypeInlineAdmin ]
+ docbow_admin.FileTypeAdmin.inlines = [PloneFileTypeInlineAdmin]
diff --git a/docbow_project/pfwb/app_settings.py b/docbow_project/pfwb/app_settings.py
index d1d755d..5e4549c 100644
--- a/docbow_project/pfwb/app_settings.py
+++ b/docbow_project/pfwb/app_settings.py
@@ -3,22 +3,23 @@
class AppSettings(object):
'''Thanks django-allauth'''
+
__DEFAULTS = dict(
# directory where ged files are stored
- PFWB_GED_DIRECTORY = None,
+ PFWB_GED_DIRECTORY=None,
# default type id for documents received by SMTP when given type does
# not exist
- PFWB_SENDMAIL_DEFAULT_TYPE_ID = None,
+ PFWB_SENDMAIL_DEFAULT_TYPE_ID=None,
# default type name if default type id does not exist
- PFWB_SENDMAIL_DEFAULT_TYPE_NAME = 'Divers',
+ PFWB_SENDMAIL_DEFAULT_TYPE_NAME='Divers',
# sender email for document received from tabellio expedition by SMTP
- PFWB_SENDMAIL_TABELLIO_EXPEDITION_EMAIL = 'commande.documents@pfwb.be',
+ PFWB_SENDMAIL_TABELLIO_EXPEDITION_EMAIL='commande.documents@pfwb.be',
# user id of senders for document received from tabellio expedition by SMTP
- PFWB_SENDMAIL_TABELLIO_EXPEDITION_USER_ID = None,
+ PFWB_SENDMAIL_TABELLIO_EXPEDITION_USER_ID=None,
# sender email for document received by SMTP (generic code)
- PFWB_SENDMAIL_ATTACHED_FILE_EMAIL = None,
+ PFWB_SENDMAIL_ATTACHED_FILE_EMAIL=None,
# user id of senders for document received by SMTP (generic code)
- PFWB_SENDMAIL_ATTACHED_FILE_USER_ID = None,
+ PFWB_SENDMAIL_ATTACHED_FILE_USER_ID=None,
)
def __init__(self, prefix):
@@ -27,22 +28,24 @@ class AppSettings(object):
@property
def settings(self):
from django.conf import settings
+
return settings
def __getattr__(self, key):
if key in self.__DEFAULTS:
- return getattr(self.settings,
- self.prefix+key, self.__DEFAULTS[key])
+ return getattr(self.settings, self.prefix + key, self.__DEFAULTS[key])
else:
from django.core.exceptions import ImproperlyConfigured
+
try:
- return getattr(self.settings, self.prefix+key)
+ return getattr(self.settings, self.prefix + key)
except AttributeError:
- raise ImproperlyConfigured('settings %s is missing' % self.prefix+key)
+ raise ImproperlyConfigured('settings %s is missing' % self.prefix + key)
app_settings = AppSettings('DOCBOW_')
app_settings.__name__ = __name__
app_settings.__file__ = __file__
import sys
+
sys.modules[__name__] = app_settings
diff --git a/docbow_project/pfwb/management/commands/archive2.py b/docbow_project/pfwb/management/commands/archive2.py
index 1dc0cdf..56cc438 100644
--- a/docbow_project/pfwb/management/commands/archive2.py
+++ b/docbow_project/pfwb/management/commands/archive2.py
@@ -21,11 +21,13 @@ def batch(qs, window):
return
after = qs[0].id
while qs.filter(id__gte=after).exists():
- yield qs.filter(id__gte=after, id__lt=after+window)
+ yield qs.filter(id__gte=after, id__lt=after + window)
after += window
+
window = 1000
+
class Command(BaseCommand):
args = ' '
help = 'Archive documents and journal'
@@ -46,39 +48,43 @@ class Command(BaseCommand):
json_path = os.path.join(doc_path, 'document.json')
with open(json_path, 'w') as document_json:
document_json.write(
- serializers.serialize('json', [document],
- indent=2, use_natural_foreign_keys=True))
+ serializers.serialize('json', [document], indent=2, use_natural_foreign_keys=True)
+ )
for attached_file in document.attached_files.all():
file_path = os.path.join(doc_path, os.path.basename(attached_file.content.name))
with open(file_path, 'wb') as data_file:
data_file.write(attached_file.content.read())
attached_file.content.close()
- attached_file_path = os.path.join(doc_path,
- 'attached_file_%s.json' % attached_file.id)
+ attached_file_path = os.path.join(doc_path, 'attached_file_%s.json' % attached_file.id)
with open(attached_file_path, 'w') as json_file:
- json_file.write(serializers.serialize('json',
- [attached_file], indent=2, use_natural_foreign_keys=True))
+ json_file.write(
+ serializers.serialize(
+ 'json', [attached_file], indent=2, use_natural_foreign_keys=True
+ )
+ )
i += len(documents)
- print(' - Archived %10d documents' % i, '\r',)
+ print(
+ ' - Archived %10d documents' % i, '\r',
+ )
sys.stdout.flush()
print('')
i = 0
for b in batch(qs, 1000):
b.delete()
i += len(documents)
- print(' - Deleted %10d documents' % i, '\r',)
+ print(
+ ' - Deleted %10d documents' % i, '\r',
+ )
sys.stdout.flush()
print('')
def save_journal(self):
- journals = Journal.objects \
- .filter(time__lte=self.before) \
- .order_by('id') \
- .select_related('tag', 'template') \
- # FIXME in django 1.11
- # .prefetch_related('objectdata_set__content_type',
- # 'stringdata_set', 'objectdata_set__tag',
- # 'stringdata_set__tag', 'objectdata_set__content_object')
+ journals = (
+ Journal.objects.filter(time__lte=self.before).order_by('id').select_related('tag', 'template')
+ ) # FIXME in django 1.11
+ # .prefetch_related('objectdata_set__content_type',
+ # 'stringdata_set', 'objectdata_set__tag',
+ # 'stringdata_set__tag', 'objectdata_set__content_object')
if not journals.exists():
return
journal_path = os.path.join(self.path, 'journal.txt')
diff --git a/docbow_project/pfwb/management/commands/sendmail.py b/docbow_project/pfwb/management/commands/sendmail.py
index 95c8d85..b06f21c 100644
--- a/docbow_project/pfwb/management/commands/sendmail.py
+++ b/docbow_project/pfwb/management/commands/sendmail.py
@@ -32,6 +32,7 @@ logger = logging.getLogger('docbow.mail_interface')
EXPEDITION = 'expedition'
ATTACHED_FILE = 'attached_file'
+
class Command(BaseCommand):
args = ''
help = '''Convert a mail to a document send.
@@ -82,11 +83,14 @@ In case of failure the following return value is returned:
def error(self, msg, exit_code=None, **kwargs):
sys.stderr.write(msg.format(**kwargs) + '\n')
if hasattr(self, 'message_id'):
- record('warning-smtp-interface', 'message {message_id} to {all_recipients} containing {filenames} refused: ' + msg,
- message_id=self.message_id,
- all_recipients=self.all_recipients,
- filenames=self.filenames,
- **kwargs)
+ record(
+ 'warning-smtp-interface',
+ 'message {message_id} to {all_recipients} containing {filenames} refused: ' + msg,
+ message_id=self.message_id,
+ all_recipients=self.all_recipients,
+ filenames=self.filenames,
+ **kwargs,
+ )
else:
record('warning-smtp-interface', 'message refused: ' + msg, **kwargs)
if exit_code:
@@ -111,7 +115,7 @@ In case of failure the following return value is returned:
def resolve_username_for_list(self, username):
if not username.startswith('liste-'):
return None
- return self.mailing_lists.get(username[len('liste-'):])
+ return self.mailing_lists.get(username[len('liste-') :])
@atomic
def handle_mail(self, mail, mail_recipients, **options):
@@ -134,8 +138,9 @@ In case of failure the following return value is returned:
ccs = mail.get_all('cc', [])
resent_tos = mail.get_all('resent-to', [])
resent_ccs = mail.get_all('resent-cc', [])
- self.all_recipients = all_recipients = mail_recipients or [b for a, b in email.utils.getaddresses(tos + ccs + resent_tos +
- resent_ccs)]
+ self.all_recipients = all_recipients = mail_recipients or [
+ b for a, b in email.utils.getaddresses(tos + ccs + resent_tos + resent_ccs)
+ ]
self.message_id = mail.get('Message-ID', None)
if not self.message_id:
self.error('7.7.1 Mail is missing a Message-ID', exit_code=6)
@@ -153,36 +158,40 @@ In case of failure the following return value is returned:
try:
filetype = models.FileType.objects.get(name=subject)
except models.FileType.DoesNotExist:
- record('warning', 'unknown filetype '
- '{filetype}, using default filetype',
- filetype=subject)
+ record('warning', 'unknown filetype ' '{filetype}, using default filetype', filetype=subject)
else:
tabellio_doc_type = mail.get('x-tabellio-doc-type')
if tabellio_doc_type:
try:
filetype = models.FileType.objects.get(
- tabelliodoctype__tabellio_doc_type=tabellio_doc_type)
+ tabelliodoctype__tabellio_doc_type=tabellio_doc_type
+ )
except models.FileType.DoesNotExist:
- record('warning', 'unknown x-tabellio-doc-type '
- '{tabellio_doc_type}, using default filetype',
- tabellio_doc_type=tabellio_doc_type)
+ record(
+ 'warning',
+ 'unknown x-tabellio-doc-type ' '{tabellio_doc_type}, using default filetype',
+ tabellio_doc_type=tabellio_doc_type,
+ )
except models.FileType.MultipleObjectsReturned:
- record('warning', 'unknown x-tabellio-doc-type '
- '{tabellio_doc_type}, using default filetype',
- tabellio_doc_type=tabellio_doc_type)
+ record(
+ 'warning',
+ 'unknown x-tabellio-doc-type ' '{tabellio_doc_type}, using default filetype',
+ tabellio_doc_type=tabellio_doc_type,
+ )
if filetype is None:
try:
- filetype = models.FileType.objects.get(
- id=app_settings.PFWB_SENDMAIL_DEFAULT_TYPE_ID)
+ filetype = models.FileType.objects.get(id=app_settings.PFWB_SENDMAIL_DEFAULT_TYPE_ID)
except models.FileType.DoesNotExist:
filetype, created = models.FileType.objects.get_or_create(
- name=app_settings.PFWB_SENDMAIL_DEFAULT_TYPE_NAME)
+ name=app_settings.PFWB_SENDMAIL_DEFAULT_TYPE_NAME
+ )
if mode == ATTACHED_FILE:
for part in mail.walk():
filename = part.get_filename(None)
- if part.get_content_type() == 'text/plain' and \
- ('Content-Disposition' not in part or 'inline' in part['Content-Disposition']):
+ if part.get_content_type() == 'text/plain' and (
+ 'Content-Disposition' not in part or 'inline' in part['Content-Disposition']
+ ):
charset = part.get_content_charset('us-ascii')
description = force_text(part.get_payload(decode=True), charset)
@@ -233,8 +242,7 @@ In case of failure the following return value is returned:
raise auth_models.User.DoesNotExist()
recipients.extend(users_qs.all())
except auth_models.User.DoesNotExist:
- msg = 'Recipient %r is not an user of the platform' \
- % email_address
+ msg = 'Recipient %r is not an user of the platform' % email_address
content_errors.append(msg)
self.filenames = [a for a, b in attachments]
if not len(attachments):
@@ -248,33 +256,40 @@ In case of failure the following return value is returned:
user_id = app_settings.PFWB_SENDMAIL_TABELLIO_EXPEDITION_USER_ID
sender = auth_models.User.objects.get(id=user_id)
except auth_models.User.DoesNotExist:
- content_errors.append('No user match the sender user_id %s in mode '
- '%s' % (user_id, mode))
+ content_errors.append('No user match the sender user_id %s in mode ' '%s' % (user_id, mode))
if content_errors:
- msg = [ '7.7.1 The email sent contains many errors:' ]
+ msg = ['7.7.1 The email sent contains many errors:']
for error in content_errors:
msg.append(' - %s' % error)
self.error('\n'.join(msg), exit_code=4)
else:
if mode == ATTACHED_FILE:
- record('smtp-received-document', 'mode: {mode} message-id: {message_id} subject: {subject}',
- mode=mode, message_id=self.message_id, subject=subject)
+ record(
+ 'smtp-received-document',
+ 'mode: {mode} message-id: {message_id} subject: {subject}',
+ mode=mode,
+ message_id=self.message_id,
+ subject=subject,
+ )
else:
- record('smtp-received-document', 'mode: {mode} message-id: '
- '{message_id} x-tabellio-doc-url: {x_tabellio_doc_url} '
- 'x-tabellio-doc-type: {x_tabellio_doc_type}',
- mode=mode, message_id=self.message_id,
- subject=repr(subject), x_tabellio_doc_url=url,
- x_tabellio_doc_type=tabellio_doc_type)
- document = models.Document(sender=sender,
- comment=description, filetype=filetype)
+ record(
+ 'smtp-received-document',
+ 'mode: {mode} message-id: '
+ '{message_id} x-tabellio-doc-url: {x_tabellio_doc_url} '
+ 'x-tabellio-doc-type: {x_tabellio_doc_type}',
+ mode=mode,
+ message_id=self.message_id,
+ subject=repr(subject),
+ x_tabellio_doc_url=url,
+ x_tabellio_doc_type=tabellio_doc_type,
+ )
+ document = models.Document(sender=sender, comment=description, filetype=filetype)
document.save()
document.to_user.set(recipients)
document.to_list.set(mailing_list_recipients)
for filename, payload in attachments:
content = ContentFile(payload)
- attached_file = models.AttachedFile(document=document,
- name=filename)
+ attached_file = models.AttachedFile(document=document, name=filename)
attached_file.content.save(filename, content, save=False)
attached_file.save()
document._timestamp = time.time()
diff --git a/docbow_project/pfwb/management/commands/sync-tabellio.py b/docbow_project/pfwb/management/commands/sync-tabellio.py
index 2eed1c5..79234b1 100644
--- a/docbow_project/pfwb/management/commands/sync-tabellio.py
+++ b/docbow_project/pfwb/management/commands/sync-tabellio.py
@@ -9,9 +9,7 @@ from sqlalchemy import create_engine, engine as sqla_engine, or_
from docbow_project.docbow.models import MailingList, DocbowProfile, FileType
from docbow_project.pfwb.models import TabellioDocType
-from docbow_project.pfwb.tabellio import (
- DBSession, TAdresse, TCom, TComppol, TPer, TPershistoline, TTypedoc
-)
+from docbow_project.pfwb.tabellio import DBSession, TAdresse, TCom, TComppol, TPer, TPershistoline, TTypedoc
""" The following variables should be defined somewhere in your
local configurration.
@@ -30,6 +28,7 @@ def get_username(last_name, first_name):
username = '%s.%s' % (slugify(first_name), slugify(last_name))
return username
+
def get_or_create_user(last_name, first_name, email, verbose, tabellio_id):
profile = None
try:
@@ -75,17 +74,16 @@ def get_or_create_user(last_name, first_name, email, verbose, tabellio_id):
class Command(BaseCommand):
-
@transaction.atomic
def handle(self, *args, **options):
- verbose = (options.get('verbosity') > 1)
+ verbose = options.get('verbosity') > 1
parl_list = MailingList.objects.get(id=settings.PARLEMENTAIRES_MAILING_ID)
ministres_list = MailingList.objects.get(id=settings.MINISTRES_MAILING_ID)
comppols = {}
- commissions_infos = {} # dict of (name, [list of pers id])
- commissions = {} # dict of list of User
+ commissions_infos = {} # dict of (name, [list of pers id])
+ commissions = {} # dict of list of User
engine = create_engine(
sqla_engine.url.URL(
@@ -94,7 +92,7 @@ class Command(BaseCommand):
password=settings.TABELLIO_DBPASSWORD,
host=settings.TABELLIO_DBHOST,
port=settings.TABELLIO_DBPORT or None,
- database=settings.TABELLIO_DBNAME
+ database=settings.TABELLIO_DBNAME,
)
)
session = DBSession(bind=engine.connect())
@@ -102,10 +100,11 @@ class Command(BaseCommand):
# get list of persons that are neither deputy or ministre so they can
# be disabled if they exists in docbow
for pers, pers_histo in session.query(TPer, TPershistoline).filter(
- TPer.id == TPershistoline.pers,
- TPer.prenom.isnot(None),
- TPershistoline.type.in_(['P_CMPL', 'M_MINT']),
- TPershistoline.fin.isnot(None)):
+ TPer.id == TPershistoline.pers,
+ TPer.prenom.isnot(None),
+ TPershistoline.type.in_(['P_CMPL', 'M_MINT']),
+ TPershistoline.fin.isnot(None),
+ ):
last_name, first_name = pers.nom, pers.prenom
@@ -132,42 +131,40 @@ class Command(BaseCommand):
ministres_list.members.remove(user)
ministres_list.save()
-
# get current deputies
deputies = {}
# in a first pass, get all of them
- for pers, pers_histo, comppol in session.query(TPer, TPershistoline, TComppol).\
- filter(
- TPer.prenom.isnot(None),
- TPershistoline.description == TComppol.id,
- TPer.id == TPershistoline.pers,
- TPershistoline.type == 'P_CMPL',
- TPershistoline.fin.is_(None)
- ):
+ for pers, pers_histo, comppol in session.query(TPer, TPershistoline, TComppol).filter(
+ TPer.prenom.isnot(None),
+ TPershistoline.description == TComppol.id,
+ TPer.id == TPershistoline.pers,
+ TPershistoline.type == 'P_CMPL',
+ TPershistoline.fin.is_(None),
+ ):
pers_id, last_name, first_name, comppol = pers.id, pers.nom, pers.prenom, comppol.abbr
deputies[pers_id] = (last_name, first_name, 'noreply@pfwb.be', comppol)
# in a second pass, overwrite those who have emails
- for pers, pers_histo, addr, comppol in session.query(TPer, TPershistoline, TAdresse, TComppol).\
- filter(
- TPer.prenom.isnot(None),
- TPershistoline.description == TComppol.id,
- TPer.id == TPershistoline.pers,
- TPershistoline.type == 'P_CMPL',
- TPershistoline.fin.is_(None),
- TAdresse.email.isnot(None),
- or_(
- TAdresse.id == TPer.addrpriv,
- TAdresse.id == TPer.addrprof1,
- TAdresse.id == TPer.addrprof2
- ),
- TAdresse.courriel.is_(True)
- ):
+ for pers, pers_histo, addr, comppol in session.query(TPer, TPershistoline, TAdresse, TComppol).filter(
+ TPer.prenom.isnot(None),
+ TPershistoline.description == TComppol.id,
+ TPer.id == TPershistoline.pers,
+ TPershistoline.type == 'P_CMPL',
+ TPershistoline.fin.is_(None),
+ TAdresse.email.isnot(None),
+ or_(TAdresse.id == TPer.addrpriv, TAdresse.id == TPer.addrprof1, TAdresse.id == TPer.addrprof2),
+ TAdresse.courriel.is_(True),
+ ):
- pers_id, last_name, first_name, email, comppol = \
- pers.id, pers.nom, pers.prenom, addr.email, comppol.abbr
+ pers_id, last_name, first_name, email, comppol = (
+ pers.id,
+ pers.nom,
+ pers.prenom,
+ addr.email,
+ comppol.abbr,
+ )
deputies[pers_id] = (last_name, first_name, email, comppol)
# get commissions
@@ -177,15 +174,13 @@ class Command(BaseCommand):
commissions[com_id] = []
for com_id in commissions.keys():
- for pers in session.query(TPer).join(
- TPershistoline, TPershistoline.pers == TPer.id
- ).filter(
- TPershistoline.description == com_id,
- TPershistoline.fin.is_(None)
+ for pers in (
+ session.query(TPer)
+ .join(TPershistoline, TPershistoline.pers == TPer.id)
+ .filter(TPershistoline.description == com_id, TPershistoline.fin.is_(None))
):
commissions_infos[com_id][1].append(pers.id)
-
deputy_users = []
for pers_id, deputy in deputies.items():
last_name, first_name, email, comppol = deputy
@@ -211,7 +206,8 @@ class Command(BaseCommand):
# create mailing lists for political groups
for comppol, members in comppols.items():
maillist, created = MailingList.objects.get_or_create(
- name=u'Appartenance politique - %s' % comppol)
+ name=u'Appartenance politique - %s' % comppol
+ )
# remove members of the list that should no longer be in there
for member in maillist.members.all():
if member not in members:
@@ -221,13 +217,13 @@ class Command(BaseCommand):
if member not in maillist.members.all():
maillist.members.add(member)
-
# get inactive comppol
query = session.query(TComppol).filter(TComppol.st == 'S_INACTIVE')
inactive_comppols = [u'Appartenance politique - %s' % comppol.abbr for comppol in query]
comppol_names = [u'Appartenance politique - %s' % comppol for comppol in comppols]
- for maillist in (MailingList.objects.filter(name__startswith='Appartenance politique -')
- .exclude(name__in=comppol_names)):
+ for maillist in MailingList.objects.filter(name__startswith='Appartenance politique -').exclude(
+ name__in=comppol_names
+ ):
maillist.members.clear()
if verbose:
print('clear', maillist)
@@ -241,8 +237,7 @@ class Command(BaseCommand):
# create mailing lists for commissions
for com_id, members in commissions.items():
com_name = commissions_infos[com_id][0]
- maillist, created = MailingList.objects.get_or_create(
- name=u'Commission - %s' % com_name)
+ maillist, created = MailingList.objects.get_or_create(name=u'Commission - %s' % com_name)
if maillist in existing_commissions:
existing_commissions.remove(maillist)
# remove members of the list that should no longer be in there
@@ -265,33 +260,27 @@ class Command(BaseCommand):
ministres = {}
# like for deputies, we have a first pass to get all of them
- for pers, pers_histo in session.query(TPer, TPershistoline).\
- filter(
- TPer.prenom.isnot(None),
- TPer.id == TPershistoline.pers,
- TPershistoline.type == 'M_MINT',
- TPershistoline.fin.is_(None)
- ):
+ for pers, pers_histo in session.query(TPer, TPershistoline).filter(
+ TPer.prenom.isnot(None),
+ TPer.id == TPershistoline.pers,
+ TPershistoline.type == 'M_MINT',
+ TPershistoline.fin.is_(None),
+ ):
pers_id, last_name, first_name = pers.id, pers.nom, pers.prenom
ministres[pers_id] = (last_name, first_name, 'noreply@pfwb.be')
# and a second pass to get the email addresses
- for pers, pers_histo, addr, in session.query(TPer, TPershistoline, TAdresse).\
- filter(
- TPer.st == 'S_MINISTRE',
- TPer.prenom.isnot(None),
- TPer.id == TPershistoline.pers,
- TPershistoline.type == 'M_MINT',
- TPershistoline.fin.is_(None),
- TAdresse.email.isnot(None),
- or_(
- TAdresse.id == TPer.addrpriv,
- TAdresse.id == TPer.addrprof1,
- TAdresse.id == TPer.addrprof2
- ),
- TAdresse.courriel.is_(True)
- ):
+ for pers, pers_histo, addr, in session.query(TPer, TPershistoline, TAdresse).filter(
+ TPer.st == 'S_MINISTRE',
+ TPer.prenom.isnot(None),
+ TPer.id == TPershistoline.pers,
+ TPershistoline.type == 'M_MINT',
+ TPershistoline.fin.is_(None),
+ TAdresse.email.isnot(None),
+ or_(TAdresse.id == TPer.addrpriv, TAdresse.id == TPer.addrprof1, TAdresse.id == TPer.addrprof2),
+ TAdresse.courriel.is_(True),
+ ):
pers_id, last_name, first_name, email = pers.id, pers.nom, pers.prenom, addr.email
ministres[pers_id] = (last_name, first_name, email)
diff --git a/docbow_project/pfwb/mellon_adapter.py b/docbow_project/pfwb/mellon_adapter.py
index 4dd0b6b..ed2bedd 100644
--- a/docbow_project/pfwb/mellon_adapter.py
+++ b/docbow_project/pfwb/mellon_adapter.py
@@ -20,7 +20,6 @@ try:
import mellon.models
class PFWBMellonAdapter(mellon.adapters.DefaultAdapter):
-
def lookup_by_attributes(self, idp, saml_attributes):
tabellio_id = get_tabellio_id(saml_attributes)
if tabellio_id:
diff --git a/docbow_project/pfwb/migrations/0001_initial.py b/docbow_project/pfwb/migrations/0001_initial.py
index 510f94d..fe4bdb7 100644
--- a/docbow_project/pfwb/migrations/0001_initial.py
+++ b/docbow_project/pfwb/migrations/0001_initial.py
@@ -14,9 +14,17 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='PloneFileType',
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ (
+ 'id',
+ models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+ ),
('plone_portal_type', models.CharField(max_length=64)),
- ('filetype', models.OneToOneField(verbose_name='Document type', to='docbow.FileType', on_delete=models.CASCADE)),
+ (
+ 'filetype',
+ models.OneToOneField(
+ verbose_name='Document type', to='docbow.FileType', on_delete=models.CASCADE
+ ),
+ ),
],
options={
'db_table': 'plone_plonefiletype',
@@ -28,9 +36,17 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='TabellioDocType',
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ (
+ 'id',
+ models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+ ),
('tabellio_doc_type', models.CharField(max_length=64, verbose_name='Tabellio doc type')),
- ('filetype', models.OneToOneField(verbose_name='Document type', to='docbow.FileType', on_delete=models.CASCADE)),
+ (
+ 'filetype',
+ models.OneToOneField(
+ verbose_name='Document type', to='docbow.FileType', on_delete=models.CASCADE
+ ),
+ ),
],
options={
'verbose_name': 'Tabellio doc type mapping',
diff --git a/docbow_project/pfwb/models.py b/docbow_project/pfwb/models.py
index b4815c7..12bf45a 100644
--- a/docbow_project/pfwb/models.py
+++ b/docbow_project/pfwb/models.py
@@ -3,8 +3,10 @@ from django.utils.translation import ugettext_lazy as _
from ..docbow.models import FileType
+
class PloneFileType(models.Model):
'''GED file type to store in exported JSON documents'''
+
filetype = models.OneToOneField(FileType, verbose_name=_('Document type'), on_delete=models.CASCADE)
plone_portal_type = models.CharField(max_length=64)
@@ -17,6 +19,7 @@ class PloneFileType(models.Model):
class TabellioDocType(models.Model):
'''Mapping from Tabellio document type to Docbow filetype'''
+
filetype = models.OneToOneField(FileType, verbose_name=_('Document type'), on_delete=models.CASCADE)
tabellio_doc_type = models.CharField(max_length=64, verbose_name=_('Tabellio doc type'))
diff --git a/docbow_project/pfwb/settings.py b/docbow_project/pfwb/settings.py
index 43d8761..1926966 100644
--- a/docbow_project/pfwb/settings.py
+++ b/docbow_project/pfwb/settings.py
@@ -5,4 +5,4 @@ DOCBOW_EDIT_EMAIL = True
PORTAL_BASE_URL = 'https://form.portail.pfwb.be'
-HELP_DIR = '/usr/share/doc/docbow/build-pfwb'
+HELP_DIR = '/usr/share/doc/docbow/build-pfwb'
diff --git a/docbow_project/pfwb/signals.py b/docbow_project/pfwb/signals.py
index a00ec4f..ecb4145 100644
--- a/docbow_project/pfwb/signals.py
+++ b/docbow_project/pfwb/signals.py
@@ -22,12 +22,12 @@ def push_document(signal, sender, instance, **kwargs):
tpl = u'{sender.first_name} {sender.last_name} ({sender.username})'
sender = tpl.format(sender=document.sender)
metadata = {
- 'document_id': document.id,
- 'plone_portal_type': plone_file_type.plone_portal_type,
- 'title': force_text(document.filetype),
- 'description': document.comment,
- 'reception_date': document.date.isoformat().split('.')[0],
- 'sender': sender,
+ 'document_id': document.id,
+ 'plone_portal_type': plone_file_type.plone_portal_type,
+ 'title': force_text(document.filetype),
+ 'description': document.comment,
+ 'reception_date': document.date.isoformat().split('.')[0],
+ 'sender': sender,
}
if attached_file.kind:
metadata['kind'] = attached_file.kind.name
diff --git a/docbow_project/pfwb/tabellio.py b/docbow_project/pfwb/tabellio.py
index 8279e6b..40458d4 100644
--- a/docbow_project/pfwb/tabellio.py
+++ b/docbow_project/pfwb/tabellio.py
@@ -3,9 +3,7 @@ https://pypi.org/project/sqlacodegen/
"""
-from sqlalchemy import (
- ARRAY, Boolean, Column, Date, DateTime, ForeignKey, Index, Integer, Text, TEXT
-)
+from sqlalchemy import ARRAY, Boolean, Column, Date, DateTime, ForeignKey, Index, Integer, Text, TEXT
from sqlalchemy.dialects.postgresql import TSVECTOR
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, sessionmaker
@@ -34,9 +32,7 @@ class TAdresse(Base):
class TPer(Base):
__tablename__ = 't_pers'
- __table_args__ = (
- Index('i_t_pers_persobjet', 'nom', 'prenom', 'initiales', unique=True),
- )
+ __table_args__ = (Index('i_t_pers_persobjet', 'nom', 'prenom', 'initiales', unique=True),)
id = Column(Text, primary_key=True)
st = Column(Text, nullable=False)
diff --git a/docbow_project/pfwb/urls.py b/docbow_project/pfwb/urls.py
index 94278ec..637600f 100644
--- a/docbow_project/pfwb/urls.py
+++ b/docbow_project/pfwb/urls.py
@@ -1,2 +1 @@
-
urlpatterns = []
diff --git a/docbow_project/pw/management/commands/sendmail.py b/docbow_project/pw/management/commands/sendmail.py
index 96b2910..7e624d6 100644
--- a/docbow_project/pw/management/commands/sendmail.py
+++ b/docbow_project/pw/management/commands/sendmail.py
@@ -32,6 +32,7 @@ ATTACHED_FILE = 'attached_file'
PRIVATE_PREFIX = 'Private - '
PRIVATE_SUFFIX = '-private'
+
class Command(BaseCommand):
args = ''
help = '''Convert a mail to a document send.
@@ -83,12 +84,16 @@ In case of failure the following return value is returned:
def error(self, msg, exit_code=None, **kwargs):
sys.stderr.write(msg.format(**kwargs))
if hasattr(self, 'message_id'):
- error_record('warning-smtp-interface', 'message {message_id} to {all_recipients} containing {filenames} with subject {subject} refused: ' + msg,
- message_id=repr(self.message_id),
- all_recipients=', '.join(map(repr, self.all_recipients)),
- filenames=', '.join(map(repr, self.filenames)),
- subject=repr(self.subject),
- **kwargs)
+ error_record(
+ 'warning-smtp-interface',
+ 'message {message_id} to {all_recipients} containing {filenames} with subject {subject} refused: '
+ + msg,
+ message_id=repr(self.message_id),
+ all_recipients=', '.join(map(repr, self.all_recipients)),
+ filenames=', '.join(map(repr, self.filenames)),
+ subject=repr(self.subject),
+ **kwargs,
+ )
else:
error_record('warning-smtp-interface', 'message refused: ' + msg, **kwargs)
if exit_code:
@@ -113,7 +118,7 @@ In case of failure the following return value is returned:
def resolve_username_for_list(self, username):
if not username.startswith('liste-'):
return None
- return self.mailing_lists.get(username[len('liste-'):])
+ return self.mailing_lists.get(username[len('liste-') :])
@atomic
def handle_mail(self, mail, mail_recipients, **options):
@@ -126,17 +131,15 @@ In case of failure the following return value is returned:
if options.get('sender'):
try:
sender = auth_models.User.objects.filter(
- Q(docbowprofile__is_guest=False)|
- Q(docbowprofile__isnull=True)).get(
- username=options['sender'])
+ Q(docbowprofile__is_guest=False) | Q(docbowprofile__isnull=True)
+ ).get(username=options['sender'])
except auth_models.User.DoesNotExist:
self.error('5.6.0 Unknown sender %r' % options['sender'], exit_code=8)
else:
try:
sender = auth_models.User.objects.filter(
- Q(docbowprofile__is_guest=False)|
- Q(docbowprofile__isnull=True)).get(
- email=from_email)
+ Q(docbowprofile__is_guest=False) | Q(docbowprofile__isnull=True)
+ ).get(email=from_email)
except auth_models.User.DoesNotExist:
content_errors.append('No sender user have mail %r' % from_email)
except MultipleObjectsReturned:
@@ -145,8 +148,9 @@ In case of failure the following return value is returned:
ccs = mail.get_all('cc', [])
resent_tos = mail.get_all('resent-to', [])
resent_ccs = mail.get_all('resent-cc', [])
- self.all_recipients = all_recipients = mail_recipients or [b for a, b in email.utils.getaddresses(tos + ccs + resent_tos +
- resent_ccs)]
+ self.all_recipients = all_recipients = mail_recipients or [
+ b for a, b in email.utils.getaddresses(tos + ccs + resent_tos + resent_ccs)
+ ]
self.message_id = mail.get('Message-ID', None)
if not self.message_id:
content_errors.append('Mail is missing a Message-ID')
@@ -161,7 +165,7 @@ In case of failure the following return value is returned:
self.subject = subject = mail.get('Subject', '')
if subject.startswith(PRIVATE_PREFIX):
self.private = True
- subject = subject[len(PRIVATE_PREFIX):]
+ subject = subject[len(PRIVATE_PREFIX) :]
if not subject:
content_errors.append('Mail is missing a filetype subject')
else:
@@ -177,8 +181,9 @@ In case of failure the following return value is returned:
for part in mail.walk():
filename = part.get_filename(None)
- if part.get_content_type() == 'text/plain' and \
- ('Content-Disposition' not in part or 'inline' in part['Content-Disposition']):
+ if part.get_content_type() == 'text/plain' and (
+ 'Content-Disposition' not in part or 'inline' in part['Content-Disposition']
+ ):
charset = part.get_content_charset('us-ascii')
for cset in (charset, 'iso-8859-15', 'utf-8'):
try:
@@ -200,7 +205,7 @@ In case of failure the following return value is returned:
username, domain = email_address.split('@', 1)
if username.endswith(PRIVATE_SUFFIX):
self.private = True
- username = username[:-len(PRIVATE_SUFFIX)]
+ username = username[: -len(PRIVATE_SUFFIX)]
email_address = '%s@%s' % (username, domain)
# mailing list case
mailing_list = self.resolve_username_for_list(username)
@@ -209,9 +214,8 @@ In case of failure the following return value is returned:
continue
# classic user case
users = auth_models.User.objects.filter(
- Q(docbowprofile__is_guest=False) |
- Q(docbowprofile__isnull=True)).filter(
- email=email_address)
+ Q(docbowprofile__is_guest=False) | Q(docbowprofile__isnull=True)
+ ).filter(email=email_address)
if users:
for user in users:
recipients.append(user)
@@ -220,8 +224,7 @@ In case of failure the following return value is returned:
user = auth_models.User.objects.get(username=username)
recipients.append(user)
except auth_models.User.DoesNotExist:
- msg = 'Recipient %r is not an user of the platform' \
- % username
+ msg = 'Recipient %r is not an user of the platform' % username
content_errors.append(msg)
self.filenames = [a for a, b in attachments]
if not len(attachments):
@@ -230,26 +233,29 @@ In case of failure the following return value is returned:
content_errors.append('You must have at least one recipient in your message.')
if content_errors:
- msg = [ '5.6.0 The email sent contains many errors:' ]
+ msg = ['5.6.0 The email sent contains many errors:']
for error in content_errors:
msg.append(' - %s' % error)
self.error('\n'.join(msg), exit_code=4)
else:
- record('smtp-received-document', 'message-id: {message_id} subject: {subject} to: {all_recipients} filenames: {filenames} private: {private}',
- message_id=self.message_id, subject=subject,
- all_recipients=', '.join(map(repr, self.all_recipients)),
- filenames=', '.join(map(repr, self.filenames)),
- private=self.private)
- document = models.Document(sender=sender,
- comment=description, filetype=filetype,
- private=self.private)
+ record(
+ 'smtp-received-document',
+ 'message-id: {message_id} subject: {subject} to: {all_recipients} filenames: {filenames} private: {private}',
+ message_id=self.message_id,
+ subject=subject,
+ all_recipients=', '.join(map(repr, self.all_recipients)),
+ filenames=', '.join(map(repr, self.filenames)),
+ private=self.private,
+ )
+ document = models.Document(
+ sender=sender, comment=description, filetype=filetype, private=self.private
+ )
document.save()
document.to_user.set(recipients)
document.to_list.set(mailing_list_recipients)
for filename, payload in attachments:
content = ContentFile(payload)
- attached_file = models.AttachedFile(document=document,
- name=filename)
+ attached_file = models.AttachedFile(document=document, name=filename)
attached_file.content.save(filename, content, save=False)
attached_file.save()
document._timestamp = time.time()
diff --git a/docbow_project/pw/models.py b/docbow_project/pw/models.py
index 784fed1..c0a39a8 100644
--- a/docbow_project/pw/models.py
+++ b/docbow_project/pw/models.py
@@ -22,8 +22,7 @@ except:
A2User.objects.using('authentic').filter(username=username).delete()
@receiver(pre_save, sender=User)
- def user_pre_save(sender, instance, raw, using, *args,
- **kwargs):
+ def user_pre_save(sender, instance, raw, using, *args, **kwargs):
'''Create new instance on authentic side'''
if using != 'default':
return
diff --git a/docbow_project/pw/settings.py b/docbow_project/pw/settings.py
index dff32ce..2ce5a05 100644
--- a/docbow_project/pw/settings.py
+++ b/docbow_project/pw/settings.py
@@ -17,28 +17,26 @@ if 'USE_SAML' in os.environ:
INSTALLED_APPS += ('mellon',)
LOGIN_URL = 'mellon_login'
LOGOUT_URL = 'mellon_logout'
- AUTHENTICATION_BACKENDS = (
- 'mellon.backends.SAMLBackend',
- )
+ AUTHENTICATION_BACKENDS = ('mellon.backends.SAMLBackend',)
MELLON_IDENTITY_PROVIDERS = {
- 'METADATA': '/etc/docbow/idp-metadata.xml',
- 'GROUP_ATTRIBUTE': 'role',
+ 'METADATA': '/etc/docbow/idp-metadata.xml',
+ 'GROUP_ATTRIBUTE': 'role',
}
MELLON_ATTRIBUTE_MAPPING = {
- 'first_name': '{attributes[sn][0]}',
- 'last_name': '{attributes[gn][0]}',
- 'email': '{attributes[mail][0]}',
+ 'first_name': '{attributes[sn][0]}',
+ 'last_name': '{attributes[gn][0]}',
+ 'email': '{attributes[mail][0]}',
}
MELLON_SUPERUSER_MAPPING = {
- 'role': ['Superutilisateur'],
+ 'role': ['Superutilisateur'],
}
MELLON_USERNAME_TEMPLATE = '{attributes[name_id_content]}'
if 'AUTHENTIC_DATABASE_ENGINE' in os.environ:
DATABASES['authentic'] = {
- 'ENGINE': os.environ.get('AUTHENTIC_DATABASE_ENGINE'),
- 'NAME': os.environ.get('AUTHENTIC_DATABASE_NAME'),
- 'USER': os.environ.get('AUTHENTIC_DATABASE_USER'),
+ 'ENGINE': os.environ.get('AUTHENTIC_DATABASE_ENGINE'),
+ 'NAME': os.environ.get('AUTHENTIC_DATABASE_NAME'),
+ 'USER': os.environ.get('AUTHENTIC_DATABASE_USER'),
}
JOURNAL_DB_FOR_ERROR_ALIAS = 'journal'
@@ -52,7 +50,7 @@ if PLATFORM == 'test':
DEFAULT_FROM_EMAIL = 'gestionnaire@pes-pw.dev.entrouvert.org'
CONTACT_SUBJECT_PREFIX = 'Contact depuis pes-pw.dev.entrouvert.org: '
-HELP_DIR = '/usr/share/doc/docbow/build-pw'
+HELP_DIR = '/usr/share/doc/docbow/build-pw'
try:
from local_settings import *
diff --git a/docbow_project/settings.py b/docbow_project/settings.py
index 7f62b1b..a35e5cd 100644
--- a/docbow_project/settings.py
+++ b/docbow_project/settings.py
@@ -4,6 +4,7 @@ import os
import logging.handlers
from django.core.exceptions import ImproperlyConfigured
+
gettext_noop = lambda s: s
BASE_DIR = os.path.dirname(__file__)
@@ -30,10 +31,10 @@ ROOT_URLCONF = 'docbow_project.urls'
STATICFILES_DIRS = ('/var/lib/%s/static/' % PROJECT_NAME,)
FILE_PER_PAGE = 30
DO_NOT_SEND_GROUPS = (
- u'Administrateurs des groupes',
- u'Administrateurs des types de document',
- u'Administrateurs des utilisateurs',
- u"Utilisateurs de l'application"
+ u'Administrateurs des groupes',
+ u'Administrateurs des types de document',
+ u'Administrateurs des utilisateurs',
+ u"Utilisateurs de l'application",
)
CONTACT_GROUPS = (u'Contact « Administrateur du système »',)
LOCALE_PATHS = (os.path.join(BASE_DIR, 'locale'),)
@@ -43,8 +44,8 @@ ALLOWED_HOSTS = ['*']
LOGIN_REDIRECT_URL = '/inbox'
MESSAGE_STORAGE = 'django.contrib.messages.storage.fallback.FallbackStorage'
AUTHENTICATION_BACKENDS = (
- 'docbow_project.docbow.auth_backend.DelegationAuthBackend',
- 'django.contrib.auth.backends.ModelBackend'
+ 'docbow_project.docbow.auth_backend.DelegationAuthBackend',
+ 'django.contrib.auth.backends.ModelBackend',
)
INTERNAL_IPS = ('127.0.0.1', '82.234.244.169')
ADMINS = ()
@@ -68,7 +69,7 @@ DOCBOW_PFWB_SENDMAIL_TABELLIO_EXPEDITION_USER_ID = None
DOCBOW_PFWB_SENDMAIL_ATTACHED_FILE_EMAIL = 'dontknow@pfwb.be'
DOCBOW_PFWB_SENDMAIL_ATTACHED_FILE_USER_ID = None
DATE_INPUT_FORMATS = ('%d/%m/%Y', '%Y-%m-%d')
-DOCBOW_MAX_FILE_SIZE = 10*1024*1024
+DOCBOW_MAX_FILE_SIZE = 10 * 1024 * 1024
DOCBOW_PRIVATE_DOCUMENTS = False
DOCBOW_BASE_URL = 'http://localhost:8000'
PLATFORM = 'prod'
@@ -82,28 +83,17 @@ TEST_RUNNER = 'django.test.runner.DiscoverRunner'
MANAGERS = ADMINS
-DATABASES = {
- 'default': {
- 'ENGINE': 'django.db.backends.postgresql_psycopg2',
- 'NAME': 'docbow',
- }
-}
+DATABASES = {'default': {'ENGINE': 'django.db.backends.postgresql_psycopg2', 'NAME': 'docbow',}}
# Hey Entr'ouvert is in France !!
-LANGUAGES = (
- ('fr', gettext_noop('French')),
-)
+LANGUAGES = (('fr', gettext_noop('French')),)
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
- 'DIRS': [
- '/var/lib/%s/templates' % PROJECT_NAME,
- os.path.join(BASE_DIR, 'docbow', 'templates')
-
- ],
+ 'DIRS': ['/var/lib/%s/templates' % PROJECT_NAME, os.path.join(BASE_DIR, 'docbow', 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
@@ -122,7 +112,6 @@ TEMPLATES = [
]
-
ATOMIC_REQUESTS = True
MIDDLEWARE = (
@@ -162,11 +151,10 @@ LOGGING = {
'version': 1,
'disable_existing_loggers': True,
'formatters': {
- 'syslog': {
- 'format': PROJECT_NAME + '(pid=%(process)d) %(levelname)s %(name)s: %(message)s',
- },
+ 'syslog': {'format': PROJECT_NAME + '(pid=%(process)d) %(levelname)s %(name)s: %(message)s',},
'syslog_debug': {
- 'format': PROJECT_NAME + '(pid=%(process)d) %(levelname)s %(asctime)s t_%(thread)s %(name)s: %(message)s',
+ 'format': PROJECT_NAME
+ + '(pid=%(process)d) %(levelname)s %(asctime)s t_%(thread)s %(name)s: %(message)s',
},
},
'handlers': {
@@ -184,26 +172,12 @@ LOGGING = {
'filters': [],
'include_html': True,
},
- 'console': {
- 'class': 'logging.StreamHandler',
- 'formatter': 'syslog_debug',
- 'level': 'DEBUG',
- },
+ 'console': {'class': 'logging.StreamHandler', 'formatter': 'syslog_debug', 'level': 'DEBUG',},
},
'loggers': {
- 'django.db': {
- 'handlers': [ ],
- 'level': 'INFO',
- 'propagate': True,
- },
- 'django.request': {
- 'handlers': [ ],
- 'propagate': True,
- },
- '': {
- 'handlers': [ 'syslog' ],
- 'level': 'INFO',
- },
+ 'django.db': {'handlers': [], 'level': 'INFO', 'propagate': True,},
+ 'django.request': {'handlers': [], 'propagate': True,},
+ '': {'handlers': ['syslog'], 'level': 'INFO',},
},
}
@@ -212,7 +186,7 @@ if DEBUG:
LOGGING['loggers']['']['handlers'].append('console')
-HELP_DIR = '/usr/share/doc/docbow/help'
+HELP_DIR = '/usr/share/doc/docbow/help'
for logger in LOGGING['loggers'].values():
if 'syslog' in logger['handlers']:
@@ -224,13 +198,17 @@ if DEBUG and not globals()['SECRET_KEY']:
if USE_DEBUG_TOOLBAR:
try:
import debug_toolbar
+
INSTALLED_APPS += ('debug_toolbar',)
except ImportError:
print("Debug toolbar missing, not loaded")
# syntax checks
for admin in ADMINS:
- assert len(admin) == 2, 'ADMINS setting must be a colon separated list of name and emails separated by a semi-colon: %s' % ADMINS
+ assert len(admin) == 2, (
+ 'ADMINS setting must be a colon separated list of name and emails separated by a semi-colon: %s'
+ % ADMINS
+ )
assert '@' in admin[1], 'ADMINS setting pairs second value must be emails: %s' % ADMINS
diff --git a/docbow_project/wsgi.py b/docbow_project/wsgi.py
index b2804a8..4a1f89b 100644
--- a/docbow_project/wsgi.py
+++ b/docbow_project/wsgi.py
@@ -18,4 +18,5 @@ import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "docbow_project.settings")
from django.core.wsgi import get_wsgi_application
+
application = get_wsgi_application()
diff --git a/mellon_settings.py b/mellon_settings.py
index 31bd7fb..d4403d1 100644
--- a/mellon_settings.py
+++ b/mellon_settings.py
@@ -7,18 +7,13 @@
INSTALLED_APPS += ('mellon',)
AUTHENTICATION_BACKENDS = (
- 'docbow_project.docbow.auth_backend.DocbowMellonAuthBackend'
- 'django.contrib.auth.backends.ModelBackend'
+ 'docbow_project.docbow.auth_backend.DocbowMellonAuthBackend' 'django.contrib.auth.backends.ModelBackend'
)
LOGIN_URL = 'mellon_login'
LOGOUT_URL = 'mellon_logout'
-MELLON_IDENTITY_PROVIDERS = [
- {
- 'METADATA': '/path/to/idp.xml'
- }
-]
+MELLON_IDENTITY_PROVIDERS = [{'METADATA': '/path/to/idp.xml'}]
MELLON_PUBLIC_KEYS = ['/path/to/saml.crt']
MELLON_PRIVATE_KEY = '/path/to/saml.key'
diff --git a/setup.py b/setup.py
index 46c5d2f..2cb1df1 100755
--- a/setup.py
+++ b/setup.py
@@ -34,7 +34,9 @@ def get_version():
if os.path.exists('.git'):
p = subprocess.Popen(
['git', 'describe', '--dirty=.dirty', '--match=v*'],
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ )
result = p.communicate()[0]
if p.returncode == 0:
result = result.decode('ascii').strip()[1:] # strip spaces/newlines and initial v
@@ -45,9 +47,7 @@ def get_version():
version = result
return version
else:
- return '0.0.post%s' % len(
- subprocess.check_output(
- ['git', 'rev-list', 'HEAD']).splitlines())
+ return '0.0.post%s' % len(subprocess.check_output(['git', 'rev-list', 'HEAD']).splitlines())
return '0.0'
@@ -64,6 +64,7 @@ class compile_translations(Command):
def run(self):
try:
from django.core.management import call_command
+
for path, dirs, files in os.walk('docbow_project'):
if 'locale' not in dirs:
continue
@@ -85,34 +86,37 @@ class install_lib(_install_lib):
_install_lib.run(self)
-setup(name='docbow',
- version=get_version(),
- license='AGPL 3.0',
- description='Document box for the Wallon Parliament',
- url='https://dev.entrouvert.org/projects/docbow-pub/',
- author="Entr'ouvert",
- author_email='info@entrouvert.com',
- maintainer='Benjamin Dauvergne',
- maintainer_email='bdauvergne@entrouvert.com',
- include_package_data=True,
- scripts=('manage.py',),
- packages=find_packages(),
- install_requires=[
- 'django>=1.11, <2',
- 'six<1.11.0',
- 'typing', # For M2Crypto.util
- 'django-debug-toolbar<0.9.0',
- 'gunicorn',
- 'django_journal>=2.0.0',
- 'django-picklefield<2.0.0',
- 'django-tables2',
- 'requests',
- 'python-magic',
- 'django-watson<1.5.4',
- 'sqlalchemy',
- ],
- cmdclass={
- 'build': build,
- 'install_lib': install_lib,
- 'compile_translations': compile_translations,
- 'sdist': eo_sdist})
+setup(
+ name='docbow',
+ version=get_version(),
+ license='AGPL 3.0',
+ description='Document box for the Wallon Parliament',
+ url='https://dev.entrouvert.org/projects/docbow-pub/',
+ author="Entr'ouvert",
+ author_email='info@entrouvert.com',
+ maintainer='Benjamin Dauvergne',
+ maintainer_email='bdauvergne@entrouvert.com',
+ include_package_data=True,
+ scripts=('manage.py',),
+ packages=find_packages(),
+ install_requires=[
+ 'django>=1.11, <2',
+ 'six<1.11.0',
+ 'typing', # For M2Crypto.util
+ 'django-debug-toolbar<0.9.0',
+ 'gunicorn',
+ 'django_journal>=2.0.0',
+ 'django-picklefield<2.0.0',
+ 'django-tables2',
+ 'requests',
+ 'python-magic',
+ 'django-watson<1.5.4',
+ 'sqlalchemy',
+ ],
+ cmdclass={
+ 'build': build,
+ 'install_lib': install_lib,
+ 'compile_translations': compile_translations,
+ 'sdist': eo_sdist,
+ },
+)
diff --git a/tests/conftest.py b/tests/conftest.py
index 6116a7d..048bb54 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -22,22 +22,16 @@ def filetypes(db):
def users(db):
result = []
for i in range(10):
- result.append(
- User.objects.create(
- username='user-%s' % i,
- email='user-%s@example.com' % i))
+ result.append(User.objects.create(username='user-%s' % i, email='user-%s@example.com' % i))
result[-1].set_password('password')
result[-1].save()
- DocbowProfile.objects.create(
- user=result[-1],
- personal_email='personal-email-user-%s@example.com' % i)
+ DocbowProfile.objects.create(user=result[-1], personal_email='personal-email-user-%s@example.com' % i)
return result
@pytest.fixture
def admin(db):
- user = User.objects.create(
- username='admin', email='admin@localhost', is_staff=True, is_superuser=True)
+ user = User.objects.create(username='admin', email='admin@localhost', is_staff=True, is_superuser=True)
user.set_password('password')
user.save()
return user
@@ -45,7 +39,6 @@ def admin(db):
@pytest.fixture
def app(django_app):
-
def login(username='user-1', password='password'):
login_page = django_app.get('/accounts/login/')
login_form = login_page.forms[0]
diff --git a/tests/main/test_commands.py b/tests/main/test_commands.py
index 7a8de9c..981d4f8 100644
--- a/tests/main/test_commands.py
+++ b/tests/main/test_commands.py
@@ -45,14 +45,15 @@ def test_forward_docs_date_filter(app, users, settings, filetypes):
assert Document.objects.filter(sender=sender).count() == 3
management.call_command(
- 'forward-docs', '%s' % recipient.pk, '%s' % new_user.pk,
+ 'forward-docs',
+ '%s' % recipient.pk,
+ '%s' % new_user.pk,
startdate=(localtime(now()) - timedelta(days=20)),
- enddate=(localtime(now()) + timedelta(days=20))
+ enddate=(localtime(now()) + timedelta(days=20)),
)
assert Document.objects.filter(sender=sender).count() == 4
- doc = Document.objects.filter(sender=sender).exclude(pk__in=[doc1.pk, doc2.pk, doc3.pk])\
- .first()
+ doc = Document.objects.filter(sender=sender).exclude(pk__in=[doc1.pk, doc2.pk, doc3.pk]).first()
assert_can_see_doc(app, doc, new_user)
diff --git a/tests/main/test_main.py b/tests/main/test_main.py
index d4631f0..fa7f652 100644
--- a/tests/main/test_main.py
+++ b/tests/main/test_main.py
@@ -22,8 +22,19 @@ import pytest
from docbow_project.docbow import app_settings, notification
from docbow_project.docbow.models import (
- Document, AttachedFile, Mailbox, Notification, DocbowProfile, MailingList, generate_filename,
- FileType, FileTypeAttachedFileKind, Delegation, all_emails, is_guest, NotificationPreference
+ Document,
+ AttachedFile,
+ Mailbox,
+ Notification,
+ DocbowProfile,
+ MailingList,
+ generate_filename,
+ FileType,
+ FileTypeAttachedFileKind,
+ Delegation,
+ all_emails,
+ is_guest,
+ NotificationPreference,
)
from docbow_project.docbow.notification import MailNotifier
from docbow_project.docbow.upload_views import file_response
@@ -40,15 +51,10 @@ def create_users(num_user):
"""
result = []
for i in range(num_user):
- result.append(
- User.objects.create(
- username='user-%s' % i,
- email='user-%s@example.com' % i))
+ result.append(User.objects.create(username='user-%s' % i, email='user-%s@example.com' % i))
result[-1].set_password('password')
result[-1].save()
- DocbowProfile.objects.create(
- user=result[-1],
- personal_email='personal-email-user-%s@example.com' % i)
+ DocbowProfile.objects.create(user=result[-1], personal_email='personal-email-user-%s@example.com' % i)
return result
@@ -59,8 +65,7 @@ def users_fixture():
@pytest.fixture
def admin():
- admin = User.objects.create(
- username='admin', email='admin@localhost', is_superuser=True, is_staff=True)
+ admin = User.objects.create(username='admin', email='admin@localhost', is_superuser=True, is_staff=True)
admin.set_password('admin')
admin.save()
return admin
@@ -83,6 +88,7 @@ def filetype_fixtures():
class MailingListTreeTestCase(TestCase):
'''Test mailing lists member resolution in a classical tree setup.'''
+
def setUp(self):
self.users = []
self.mls = []
@@ -90,11 +96,10 @@ class MailingListTreeTestCase(TestCase):
self.users.append(User.objects.create(username='%s' % i))
sublist = []
for i in range(19, -1, -1):
- self.mls.insert(0, MailingList.objects.create(
- name='%s' % i))
+ self.mls.insert(0, MailingList.objects.create(name='%s' % i))
self.mls[0].members.set([self.users[i]])
self.mls[0].mailing_list_members.set(sublist)
- sublist = [ self.mls[0] ]
+ sublist = [self.mls[0]]
def test_mailing_list_recursive(self):
"""
@@ -102,7 +107,7 @@ class MailingListTreeTestCase(TestCase):
"""
for i in range(19, -1, -1):
members = self.mls[i].recursive_members()
- self.assertEqual(len(members), 20-i)
+ self.assertEqual(len(members), 20 - i)
def test_mailing_list_recursive_with_origin(self):
"""
@@ -110,13 +115,14 @@ class MailingListTreeTestCase(TestCase):
"""
for i in range(19, -1, -1):
mwo = self.mls[i].recursive_members_with_origin()
- self.assertEqual(len(mwo), 20-i)
+ self.assertEqual(len(mwo), 20 - i)
for j in range(i, 20):
- self.assertEqual(mwo[self.users[j]], set(self.mls[i:j+1]))
+ self.assertEqual(mwo[self.users[j]], set(self.mls[i : j + 1]))
class MailingListCycle(TestCase):
'''Test mailing lists member resolution in a cyclic setup.'''
+
def setUp(self):
self.users = []
self.mls = []
@@ -124,11 +130,10 @@ class MailingListCycle(TestCase):
self.users.append(User.objects.create(username='%s' % i))
sublist = []
for i in range(19, -1, -1):
- self.mls.insert(0, MailingList.objects.create(
- name='%s' % i))
+ self.mls.insert(0, MailingList.objects.create(name='%s' % i))
self.mls[0].members.set([self.users[i]])
self.mls[0].mailing_list_members.set(sublist)
- sublist = [ self.mls[0] ]
+ sublist = [self.mls[0]]
self.mls[19].mailing_list_members.set([self.mls[0]])
def test_mailing_list_recursive(self):
@@ -152,31 +157,29 @@ class MailingListCycle(TestCase):
@override_settings(MEDIA_ROOT=MEDIA_ROOT)
class BaseTestCase(TestCase):
- COUNT = 10
+ COUNT = 10
- def setUp(self):
- self.setUpUsers()
- self.setUpDocuments()
+ def setUp(self):
+ self.setUpUsers()
+ self.setUpDocuments()
- def setUpUsers(self):
- self.users = create_users(self.COUNT)
- self.filetypes = create_filetypes(self.COUNT)
+ def setUpUsers(self):
+ self.users = create_users(self.COUNT)
+ self.filetypes = create_filetypes(self.COUNT)
+
+ def setUpDocuments(self):
+ self.documents = []
+ for i in range(self.COUNT):
+ self.documents.append(
+ Document.objects.create(sender=self.users[(i + 2) % self.COUNT], filetype=self.filetypes[i])
+ )
+ self.documents[-1].to_user.set([self.users[i % self.COUNT], self.users[(i + 1) % self.COUNT]])
+ for j in range(2):
+ attached_file = AttachedFile(name='file%s' % j, document=self.documents[-1], kind=None)
+ attached_file.content.save('file%s.pdf' % j, ContentFile('coucou'))
+ attached_file.save()
+ self.documents[-1].post()
- def setUpDocuments(self):
- self.documents = []
- for i in range(self.COUNT):
- self.documents.append(
- Document.objects.create(sender=self.users[(i+2) % self.COUNT],
- filetype=self.filetypes[i]))
- self.documents[-1].to_user.set([self.users[i % self.COUNT],
- self.users[(i+1) % self.COUNT]])
- for j in range(2):
- attached_file = AttachedFile(name='file%s' % j,
- document=self.documents[-1],
- kind=None)
- attached_file.content.save('file%s.pdf' % j, ContentFile('coucou'))
- attached_file.save()
- self.documents[-1].post()
class BasicTestCase(BaseTestCase):
def test_notification_mail(self):
@@ -194,138 +197,134 @@ class BasicTestCase(BaseTestCase):
match = MAIL_LINK_RE.search(message.body)
self.assertIsNotNone(match)
+
class UtilsTestCase(BaseTestCase):
- def setUp(self):
- super(UtilsTestCase, self).setUp()
- self.user1, self.user2 = self.users[:2]
- self.user2.docbowprofile.is_guest = True
- self.user2.docbowprofile.save()
+ def setUp(self):
+ super(UtilsTestCase, self).setUp()
+ self.user1, self.user2 = self.users[:2]
+ self.user2.docbowprofile.is_guest = True
+ self.user2.docbowprofile.save()
- def test_generate_filename(self):
- assert generate_filename(None, 'xxx.pdf') != generate_filename(None, 'xxx.pdf')
+ def test_generate_filename(self):
+ assert generate_filename(None, 'xxx.pdf') != generate_filename(None, 'xxx.pdf')
- def test_all_emails(self):
- assert set(all_emails(self.user1)) == \
- set((self.user1.email, self.user1.docbowprofile.personal_email))
+ def test_all_emails(self):
+ assert set(all_emails(self.user1)) == set((self.user1.email, self.user1.docbowprofile.personal_email))
- def test_document_manager(self):
- with self.assertNumQueries(1):
- # With django 1.8, there is no more
- # eager loading of related AttachedFile objects
- # so only one SQL query here
- list(Document.objects.all())
+ def test_document_manager(self):
+ with self.assertNumQueries(1):
+ # With django 1.8, there is no more
+ # eager loading of related AttachedFile objects
+ # so only one SQL query here
+ list(Document.objects.all())
- def test_document_accessors(self):
- document = self.documents[0]
- filenames = set([filename.strip() for filename in document.filenames().split(',')])
- self.assertEqual(filenames, set(['file0.pdf', 'file1.pdf']))
- self.assertEqual(set(document.user_human_to()),
- set(['user-0', 'user-1']))
- self.assertEqual(document.group_human_to(), [])
- self.assertEqual(set(document.human_to()),
- set(['user-0', 'user-1']))
- self.assertIsNotNone(document.filename_links())
- assert set(document.to()) == set((self.user1, self.user2))
- assert dict(document.to_with_origin()) == \
- {self.user1: set([ '--direct--' ]), self.user2: set(['--direct--'])}
- self.assertEqual(sorted(map(lambda x: x.pk, document.delivered_to())),
- sorted([ self.user1.pk, self.user2.pk]))
+ def test_document_accessors(self):
+ document = self.documents[0]
+ filenames = set([filename.strip() for filename in document.filenames().split(',')])
+ self.assertEqual(filenames, set(['file0.pdf', 'file1.pdf']))
+ self.assertEqual(set(document.user_human_to()), set(['user-0', 'user-1']))
+ self.assertEqual(document.group_human_to(), [])
+ self.assertEqual(set(document.human_to()), set(['user-0', 'user-1']))
+ self.assertIsNotNone(document.filename_links())
+ assert set(document.to()) == set((self.user1, self.user2))
+ assert dict(document.to_with_origin()) == {
+ self.user1: set(['--direct--']),
+ self.user2: set(['--direct--']),
+ }
+ self.assertEqual(
+ sorted(map(lambda x: x.pk, document.delivered_to())), sorted([self.user1.pk, self.user2.pk])
+ )
- def test_is_guest(self):
- self.assertTrue(is_guest(self.user2))
+ def test_is_guest(self):
+ self.assertTrue(is_guest(self.user2))
class DelegatesTestCase(BaseTestCase):
- def setUp(self):
- self.setUpUsers()
- self.delegate = delegate = User(username='delegate')
- delegate.set_password('delegate')
- delegate.save()
- Delegation.objects.create(by=self.users[0], to=delegate)
- Delegation.objects.create(by=self.users[1], to=delegate)
- self.guest0 = User(username='user-0-1')
- self.guest0.set_password('guest')
- self.guest0.save()
- DocbowProfile.objects.create(
- user=self.guest0, is_guest=True)
- Delegation.objects.create(
- by=self.users[0], to=self.guest0)
- self.guest1 = User(username='user-1-1')
- self.guest1.set_password('guest')
- self.guest1.save()
- DocbowProfile.objects.create(
- user=self.guest1, is_guest=True)
- Delegation.objects.create(
- by=self.users[1], to=self.guest1)
+ def setUp(self):
+ self.setUpUsers()
+ self.delegate = delegate = User(username='delegate')
+ delegate.set_password('delegate')
+ delegate.save()
+ Delegation.objects.create(by=self.users[0], to=delegate)
+ Delegation.objects.create(by=self.users[1], to=delegate)
+ self.guest0 = User(username='user-0-1')
+ self.guest0.set_password('guest')
+ self.guest0.save()
+ DocbowProfile.objects.create(user=self.guest0, is_guest=True)
+ Delegation.objects.create(by=self.users[0], to=self.guest0)
+ self.guest1 = User(username='user-1-1')
+ self.guest1.set_password('guest')
+ self.guest1.save()
+ DocbowProfile.objects.create(user=self.guest1, is_guest=True)
+ Delegation.objects.create(by=self.users[1], to=self.guest1)
- def test_inbox_by_document(self):
- document = Document.objects.create(
- sender=self.users[0], filetype=self.filetypes[0])
- document.to_user.set([self.users[1]])
- attached_file = AttachedFile(name='file-private-flag.pdf', document=document, kind=None)
- attached_file.content.save('file-private-flag.pdf', ContentFile('coucou'))
- attached_file.save()
- document.post()
- c = Client()
- c.login(username='delegate', password='delegate')
- response = c.get('/inbox/%s/' % document.pk)
- self.assertEqual(response.status_code, 200)
+ def test_inbox_by_document(self):
+ document = Document.objects.create(sender=self.users[0], filetype=self.filetypes[0])
+ document.to_user.set([self.users[1]])
+ attached_file = AttachedFile(name='file-private-flag.pdf', document=document, kind=None)
+ attached_file.content.save('file-private-flag.pdf', ContentFile('coucou'))
+ attached_file.save()
+ document.post()
+ c = Client()
+ c.login(username='delegate', password='delegate')
+ response = c.get('/inbox/%s/' % document.pk)
+ self.assertEqual(response.status_code, 200)
- def test_private_flag(self):
- document = Document.objects.create(sender=self.users[0], filetype=self.filetypes[0], private=True)
- document.to_user.set([self.users[1]])
- attached_file = AttachedFile(name='file-private-flag.pdf', document=document, kind=None)
- attached_file.content.save('file-private-flag.pdf', ContentFile('coucou'))
- attached_file.save()
- document.post()
- self.assertEqual(Mailbox.objects.count(), 2)
+ def test_private_flag(self):
+ document = Document.objects.create(sender=self.users[0], filetype=self.filetypes[0], private=True)
+ document.to_user.set([self.users[1]])
+ attached_file = AttachedFile(name='file-private-flag.pdf', document=document, kind=None)
+ attached_file.content.save('file-private-flag.pdf', ContentFile('coucou'))
+ attached_file.save()
+ document.post()
+ self.assertEqual(Mailbox.objects.count(), 2)
- # check user-1 sees document in its outbox
- c = Client()
- c.login(username='user-0', password='password')
+ # check user-1 sees document in its outbox
+ c = Client()
+ c.login(username='user-0', password='password')
- response = c.get('/outbox/')
- self.assertIn('/outbox/%s/' % document.pk, force_text(response.content))
- response = c.get('/outbox/%s/' % document.pk)
- self.assertEqual(response.status_code, 200)
+ response = c.get('/outbox/')
+ self.assertIn('/outbox/%s/' % document.pk, force_text(response.content))
+ response = c.get('/outbox/%s/' % document.pk)
+ self.assertEqual(response.status_code, 200)
- response = c.get('/inbox/')
- self.assertNotIn('/inbox/%s/' % document.pk, force_text(response.content))
- response = c.get('/inbox/%s/' % document.pk)
- self.assertEqual(response.status_code, 302)
+ response = c.get('/inbox/')
+ self.assertNotIn('/inbox/%s/' % document.pk, force_text(response.content))
+ response = c.get('/inbox/%s/' % document.pk)
+ self.assertEqual(response.status_code, 302)
- # check user-1 sees document in its inbox
- c = Client()
- c.login(username='user-1', password='password')
+ # check user-1 sees document in its inbox
+ c = Client()
+ c.login(username='user-1', password='password')
- response = c.get('/inbox/')
- self.assertIn('/inbox/%s/' % document.pk, force_text(response.content))
- response = c.get('/inbox/%s/' % document.pk)
- self.assertEqual(response.status_code, 200)
+ response = c.get('/inbox/')
+ self.assertIn('/inbox/%s/' % document.pk, force_text(response.content))
+ response = c.get('/inbox/%s/' % document.pk)
+ self.assertEqual(response.status_code, 200)
- response = c.get('/outbox/%s/' % document.pk)
- self.assertEqual(response.status_code, 302)
- response = c.get('/outbox/')
- self.assertNotIn('/outbox/%s/' % document.pk, force_text(response.content))
+ response = c.get('/outbox/%s/' % document.pk)
+ self.assertEqual(response.status_code, 302)
+ response = c.get('/outbox/')
+ self.assertNotIn('/outbox/%s/' % document.pk, force_text(response.content))
- # check delegate sees nothing
- c = Client()
- c.login(username='delegate', password='delegate')
+ # check delegate sees nothing
+ c = Client()
+ c.login(username='delegate', password='delegate')
- response = c.get('/inbox/')
- self.assertNotIn('/inbox/%s/' % document.pk, force_text(response.content))
- response = c.get('/inbox/%s/' % document.pk)
- self.assertEqual(response.status_code, 302)
+ response = c.get('/inbox/')
+ self.assertNotIn('/inbox/%s/' % document.pk, force_text(response.content))
+ response = c.get('/inbox/%s/' % document.pk)
+ self.assertEqual(response.status_code, 302)
- response = c.get('/outbox/')
- self.assertNotIn('/outbox/%s/' % document.pk, force_text(response.content))
- response = c.get('/outbox/%s/' % document.pk)
- self.assertEqual(response.status_code, 302)
+ response = c.get('/outbox/')
+ self.assertNotIn('/outbox/%s/' % document.pk, force_text(response.content))
+ response = c.get('/outbox/%s/' % document.pk)
+ self.assertEqual(response.status_code, 302)
- # check notifications
- with self.assertRaises(Notification.DoesNotExist):
- Notification.objects.get(user=self.delegate, document=document)
- Notification.objects.get(user=self.users[1], document=document)
+ # check notifications
+ with self.assertRaises(Notification.DoesNotExist):
+ Notification.objects.get(user=self.delegate, document=document)
+ Notification.objects.get(user=self.users[1], document=document)
class DummyNotifier(notification.BaseNotifier):
@@ -346,15 +345,11 @@ class NotificationTestCase(BaseTestCase):
def test_notification_preferences(self):
NotificationPreference.objects.create(
- user=self.users[0],
- kind=DummyNotifier.key,
- filetype=self.filetypes[0],
- value=False)
+ user=self.users[0], kind=DummyNotifier.key, filetype=self.filetypes[0], value=False
+ )
NotificationPreference.objects.create(
- user=self.users[1],
- kind=DummyNotifier.key,
- filetype=self.filetypes[1],
- value=False)
+ user=self.users[1], kind=DummyNotifier.key, filetype=self.filetypes[1], value=False
+ )
DummyNotifier.notifications = []
with mock.patch('docbow_project.docbow.notification.get_notifiers') as MockClass:
@@ -365,17 +360,20 @@ class NotificationTestCase(BaseTestCase):
for notif in DummyNotifier.notifications:
with self.assertRaises(NotificationPreference.DoesNotExist):
NotificationPreference.objects.get(
- user=notif.user,
- filetype=notif.document.filetype,
- kind=DummyNotifier.key,
- value=False)
+ user=notif.user, filetype=notif.document.filetype, kind=DummyNotifier.key, value=False
+ )
@override_settings(MEDIA_ROOT=MEDIA_ROOT)
class NotificationToDelegatesTestCase(TestCase):
- def send_document(self, sender, user_recipients=[], list_recipients=[],
- filetype_name='dummy filetype',
- names_and_contents=(('dummy.pdf', 'dummy content'),)):
+ def send_document(
+ self,
+ sender,
+ user_recipients=[],
+ list_recipients=[],
+ filetype_name='dummy filetype',
+ names_and_contents=(('dummy.pdf', 'dummy content'),),
+ ):
filetype, created = FileType.objects.get_or_create(name=filetype_name)
document = Document.objects.create(sender=sender, filetype=filetype)
@@ -383,8 +381,7 @@ class NotificationToDelegatesTestCase(TestCase):
document.to_list.set(list_recipients)
attached_files = []
for name, content in names_and_contents:
- attached_file = AttachedFile(name=name,
- document=document, kind=None)
+ attached_file = AttachedFile(name=name, document=document, kind=None)
attached_file.content.save(name, ContentFile(content))
attached_file.save()
attached_files.append(attached_file)
@@ -405,8 +402,9 @@ class NotificationToDelegatesTestCase(TestCase):
notification.process_notifications()
self.assertEqual(len(DummyNotifier.notifications), 2)
- self.assertEqual(set([notif.user for notif in
- DummyNotifier.notifications]), set([recipient, delegate]))
+ self.assertEqual(
+ set([notif.user for notif in DummyNotifier.notifications]), set([recipient, delegate])
+ )
delegate.is_active = False
delegate.save()
@@ -418,7 +416,6 @@ class NotificationToDelegatesTestCase(TestCase):
class AddListTestCase(BaseTestCase):
-
def test_add_mailing_list(self):
management.call_command('add-list', 'some-ml-name')
ml_list = MailingList.objects.all()
@@ -427,17 +424,22 @@ class AddListTestCase(BaseTestCase):
@pytest.mark.django_db
-def test_send_file(
- users_fixture, filetype_fixtures, settings,
- tmpdir, monkeypatch):
+def test_send_file(users_fixture, filetype_fixtures, settings, tmpdir, monkeypatch):
settings.MEDIA_ROOT = tmpdir.strpath
monkeypatch.chdir(tmpdir)
filetosend = tmpdir.join('filetosend.txt')
filetosend.write("file content")
management.call_command(
- 'sendfile', '--sender', 'user-1', '--to-user', 'user-2',
- '--filetype', 'filetype-1', '--description', 'yes we can',
- 'filetosend.txt'
+ 'sendfile',
+ '--sender',
+ 'user-1',
+ '--to-user',
+ 'user-2',
+ '--filetype',
+ 'filetype-1',
+ '--description',
+ 'yes we can',
+ 'filetosend.txt',
)
docs = Document.objects.all()
assert len(docs) == 1
@@ -468,12 +470,13 @@ def test_signals(users_fixture, settings, monkeypatch, tmpdir):
return {'user': 'test-user', 'ip': '0.0.0.0'}
import docbow_project.docbow.signals
+
user0 = users_fixture[0]
- monkeypatch.setattr(
- docbow_project.docbow.signals, 'middleware', MockMiddleware())
+ monkeypatch.setattr(docbow_project.docbow.signals, 'middleware', MockMiddleware())
# We just need no exception raised
docbow_project.docbow.signals.modified_data(
- sender=User, instance=user0, created=False, raw=False, using='default')
+ sender=User, instance=user0, created=False, raw=False, using='default'
+ )
def test_file_response(tmpdir):
@@ -500,7 +503,8 @@ def test_file_match_mime_types(tmpdir):
def test_filetype_attached_file_kind(db, tmpdir):
ft = FileType.objects.create(name='some file type')
fta = FileTypeAttachedFileKind.objects.create(
- name='text-plain', file_type=ft, mime_types='text/plain', position=1)
+ name='text-plain', file_type=ft, mime_types='text/plain', position=1
+ )
text_file = tmpdir.join('aaa.txt')
with text_file.open('w') as f:
@@ -520,6 +524,7 @@ def test_password_reset(users_fixture, settings, monkeypatch, client):
client.login(username='user-1@example.com', password='password')
import django.contrib.auth.forms
+
email_message = mock.Mock()
email_message_factory = mock.Mock(return_value=email_message)
@@ -558,9 +563,7 @@ def test_password_reset_confirm_post(users_fixture, client):
redirect_url = '/accounts/password/reset/confirm/%s/set-password/' % uid
assert response['Location'].endswith(redirect_url)
- response = client.post(
- redirect_url,
- {'new_password1': 'newpass', 'new_password2': 'newpass'})
+ response = client.post(redirect_url, {'new_password1': 'newpass', 'new_password2': 'newpass'})
assert response.status_code == 302
assert response['Location'].endswith('/accounts/password/reset/complete/')
@@ -588,13 +591,12 @@ def test_delegate_login(client):
delegate = User.objects.create(username='recipient-1')
delegate.set_password('password')
delegate.save()
- DocbowProfile.objects.create(
- user=delegate, is_guest=True)
+ DocbowProfile.objects.create(user=delegate, is_guest=True)
Delegation.objects.create(by=recipient, to=delegate)
response = client.post(
- '/accounts/login/?next=/inbox/',
- {'username': 'recipient-1', 'password': 'password'})
+ '/accounts/login/?next=/inbox/', {'username': 'recipient-1', 'password': 'password'}
+ )
assert response.status_code == 302
assert response['Location'].endswith('inbox/')
@@ -607,12 +609,11 @@ def test_delegate_login_hyphen_in_user_name(client):
delegate = User.objects.create(username='recipient-tricky-1')
delegate.set_password('password')
delegate.save()
- DocbowProfile.objects.create(
- user=delegate, is_guest=True)
+ DocbowProfile.objects.create(user=delegate, is_guest=True)
Delegation.objects.create(by=recipient, to=delegate)
response = client.post(
- '/accounts/login/?next=/inbox/',
- {'username': 'recipient-tricky-1', 'password': 'password'})
+ '/accounts/login/?next=/inbox/', {'username': 'recipient-tricky-1', 'password': 'password'}
+ )
assert response.status_code == 302
assert response['Location'].endswith('inbox/')
diff --git a/tests/main/test_views.py b/tests/main/test_views.py
index 49df81a..16048b7 100644
--- a/tests/main/test_views.py
+++ b/tests/main/test_views.py
@@ -9,7 +9,12 @@ import pytest
from webtest import Upload
from docbow_project.docbow.models import (
- AttachedFile, DeletedDocument, Document, FileType, MailingList, FileTypeAttachedFileKind
+ AttachedFile,
+ DeletedDocument,
+ Document,
+ FileType,
+ MailingList,
+ FileTypeAttachedFileKind,
)
from utils import assert_can_see_doc, assert_cannot_see_doc, send_file
@@ -102,8 +107,7 @@ def test_sendfile_selector(app, filetypes, users):
def test_sendfile(app, filetypes, users, settings):
settings.MEDIA_ROOT = MEDIA_ROOT
sender = User.objects.get(username='user-1')
- recipient1, recipient2 = \
- User.objects.get(username='user-2'), User.objects.get(username='user-3')
+ recipient1, recipient2 = User.objects.get(username='user-2'), User.objects.get(username='user-3')
app.login()
ft = FileType.objects.first()
resp = app.get('/send_file/%s/' % ft.pk)
@@ -127,8 +131,7 @@ def test_sendfile_mailing_list(app, filetypes, users, settings):
settings.MEDIA_ROOT = MEDIA_ROOT
sender = User.objects.get(username='user-1')
ml = MailingList.objects.create(name='test')
- recipient1, recipient2 = \
- User.objects.get(username='user-2'), User.objects.get(username='user-3')
+ recipient1, recipient2 = User.objects.get(username='user-2'), User.objects.get(username='user-3')
ml.members.add(recipient1, recipient2)
ft = FileType.objects.first()
@@ -364,8 +367,9 @@ def test_upload_file(app, users, settings):
app.login(username='user-1')
upload_id = str(uuid.uuid4())
resp = app.post(
- '/upload/%s/' % upload_id, headers={'Accept': 'application/json'},
- upload_files=[('file', 'readme.rst', b'data')]
+ '/upload/%s/' % upload_id,
+ headers={'Accept': 'application/json'},
+ upload_files=[('file', 'readme.rst', b'data')],
)
assert resp.status_code == 200
json = resp.json
diff --git a/tests/pfwb/test_pfwb.py b/tests/pfwb/test_pfwb.py
index 088fb1d..f36c90e 100644
--- a/tests/pfwb/test_pfwb.py
+++ b/tests/pfwb/test_pfwb.py
@@ -18,6 +18,7 @@ import mock
MEDIA_ROOT = tempfile.mkdtemp()
+
@contextmanager
def captured_output():
new_out, new_err = StringIO(), StringIO()
@@ -28,6 +29,7 @@ def captured_output():
finally:
sys.stdout, sys.stderr = old_out, old_err
+
class stderr_output(object):
def __init__(self, output):
self.output = output
@@ -39,8 +41,10 @@ class stderr_output(object):
ret = func(testcase, *args, **kwargs)
testcase.assertEqual(self.output, err.getvalue())
return ret
+
return f
+
class stdout_output(object):
def __init__(self, output):
self.output = output
@@ -52,16 +56,17 @@ class stdout_output(object):
ret = func(testcase, *args, **kwargs)
testcase.assertEqual(self.output, out.getvalue())
return ret
+
return f
+
from django.test import TestCase
from django.test.utils import override_settings
from django.core import management
from django.contrib.auth.models import User
from docbow_project.pfwb.models import TabellioDocType, PloneFileType
-from docbow_project.docbow.models import (FileType, MailingList, Document,
- AttachedFile)
+from docbow_project.docbow.models import FileType, MailingList, Document, AttachedFile
from django_journal.models import Journal
@@ -71,7 +76,6 @@ RECIPIENT_LIST_EMAIL = 'liste-ma-liste@example.com'
class MockUrlib(object):
-
def urlopen(self, url):
return self
@@ -92,28 +96,27 @@ mockurllib = MockUrlib()
class SendMailTestCase(TestCase):
def setUp(self):
self.pjd_filetype = FileType.objects.create(name='PJD', id=2)
- self.tabellio_doc_type = TabellioDocType.objects.create(filetype=self.pjd_filetype,
- tabellio_doc_type='PJD')
+ self.tabellio_doc_type = TabellioDocType.objects.create(
+ filetype=self.pjd_filetype, tabellio_doc_type='PJD'
+ )
self.expedition_user = User.objects.create(username='expedition', id=1)
self.to_user = User.objects.create(username='recipient', email=RECIPIENT_EMAIL, id=2)
self.to_list = MailingList.objects.create(name='ma liste')
self.to_list.members.add(self.to_user)
- def send_tabellio_doc2(self, content, expedition_email, recipient_email, doc_type,
- subject):
- content = content % { 'expedition_email': expedition_email,
- 'recipient_email': recipient_email,
- 'doc_type': doc_type,
- 'subject': subject
- }
+ def send_tabellio_doc2(self, content, expedition_email, recipient_email, doc_type, subject):
+ content = content % {
+ 'expedition_email': expedition_email,
+ 'recipient_email': recipient_email,
+ 'doc_type': doc_type,
+ 'subject': subject,
+ }
with tempfile.NamedTemporaryFile() as f:
f.write(force_bytes(content))
f.flush()
- management.call_command('sendmail', recipient_email, file=f.name,
- sender=expedition_email)
+ management.call_command('sendmail', recipient_email, file=f.name, sender=expedition_email)
- def send_tabellio_doc(self, expedition_email, recipient_email, doc_type,
- subject):
+ def send_tabellio_doc(self, expedition_email, recipient_email, doc_type, subject):
content = '''\
Message-ID: <232323232@example.com>
From: %(expedition_email)s
@@ -129,8 +132,7 @@ Status: RO
Coucou
'''
- self.send_tabellio_doc2(content, expedition_email, recipient_email,
- doc_type, subject)
+ self.send_tabellio_doc2(content, expedition_email, recipient_email, doc_type, subject)
@stderr_output('7.7.1 No sender\n7.7.1 No sender\n')
def test_fail_sender(self):
@@ -142,7 +144,8 @@ Coucou
@stderr_output('7.7.1 Mail is missing a Message-ID\n')
def test_fail_on_missing_message_id(self):
with self.assertRaises(SystemExit):
- self.send_tabellio_doc2('''From: %(expedition_email)s
+ self.send_tabellio_doc2(
+ '''From: %(expedition_email)s
To: %(recipient_email)s
Subject: %(subject)s
MIME-Version: 1.0
@@ -153,13 +156,19 @@ X-Tabellio-Doc-Type: %(doc_type)s
X-Tabellio-Doc-URL: https://buildmedia.readthedocs.org/media/pdf/django/2.2.x/django.pdf
Status: RO
-Coucou''', EXPEDITION_EMAIL, RECIPIENT_EMAIL, 'PJD', 'Mouais: monfichier.pdf')
+Coucou''',
+ EXPEDITION_EMAIL,
+ RECIPIENT_EMAIL,
+ 'PJD',
+ 'Mouais: monfichier.pdf',
+ )
@stderr_output('7.7.1 Mail is missing a subject\n')
def test_fail_on_missing_subject(self):
with mock.patch('docbow_project.pfwb.management.commands.sendmail.urlopen', mockurllib.urlopen):
with self.assertRaises(SystemExit):
- self.send_tabellio_doc2('''From: %(expedition_email)s
+ self.send_tabellio_doc2(
+ '''From: %(expedition_email)s
Message-ID: <232323232@example.com>
To: %(recipient_email)s
MIME-Version: 1.0
@@ -170,7 +179,12 @@ X-Tabellio-Doc-Type: %(doc_type)s
X-Tabellio-Doc-URL: https://buildmedia.readthedocs.org/media/pdf/django/2.2.x/django.pdf
Status: RO
-Coucou''', EXPEDITION_EMAIL, RECIPIENT_EMAIL, 'PJD', 'Mouais: monfichier.pdf')
+Coucou''',
+ EXPEDITION_EMAIL,
+ RECIPIENT_EMAIL,
+ 'PJD',
+ 'Mouais: monfichier.pdf',
+ )
@stderr_output('7.7.1 Filename cannot be extracted from the subject\n')
def test_fail_on_missing_colon_in_subject(self):
@@ -178,7 +192,9 @@ Coucou''', EXPEDITION_EMAIL, RECIPIENT_EMAIL, 'PJD', 'Mouais: monfichier.pdf')
with self.assertRaises(SystemExit):
self.send_tabellio_doc(EXPEDITION_EMAIL, RECIPIENT_EMAIL, 'PJD', 'Mouais')
- @stderr_output("7.7.1 The email sent contains many errors:\n - Recipient 'xxx@xx.com' is not an user of the platform\n")
+ @stderr_output(
+ "7.7.1 The email sent contains many errors:\n - Recipient 'xxx@xx.com' is not an user of the platform\n"
+ )
def test_fail_on_unknown_user(self):
with mock.patch('docbow_project.pfwb.management.commands.sendmail.urlopen', mockurllib.urlopen):
with self.assertRaises(SystemExit):
@@ -189,10 +205,12 @@ Coucou''', EXPEDITION_EMAIL, RECIPIENT_EMAIL, 'PJD', 'Mouais: monfichier.pdf')
with mock.patch('docbow_project.pfwb.management.commands.sendmail.urlopen', mockurllib.urlopen):
self.assertEqual(FileType.objects.filter(name='Default').count(), 0)
self.send_tabellio_doc(EXPEDITION_EMAIL, RECIPIENT_EMAIL, 'XXX', 'Mouais: monfichier.pdf')
- self.assertEqual(Journal.objects.order_by('id')[0].message, 'unknown x-tabellio-doc-type XXX, using default filetype')
+ self.assertEqual(
+ Journal.objects.order_by('id')[0].message,
+ 'unknown x-tabellio-doc-type XXX, using default filetype',
+ )
self.assertEqual(FileType.objects.filter(name='Default').count(), 1)
-
@stderr_output('')
def test_expedition_mode(self):
"""
@@ -214,7 +232,6 @@ Coucou''', EXPEDITION_EMAIL, RECIPIENT_EMAIL, 'PJD', 'Mouais: monfichier.pdf')
assert Document.objects.get().to_user.count() == 1
assert Document.objects.get().to_list.count() == 0
-
@stderr_output('')
def test_expedition_mode_to_list(self):
"""
@@ -227,6 +244,7 @@ Coucou''', EXPEDITION_EMAIL, RECIPIENT_EMAIL, 'PJD', 'Mouais: monfichier.pdf')
assert Document.objects.get().to_list.count() == 1
assert Document.objects.get().to_list.all()[0] == self.to_list
+
@override_settings(DOCBOW_PFWB_SENDMAIL_DEFAULT_TYPE_ID=1)
@override_settings(DOCBOW_PFWB_SENDMAIL_DEFAULT_TYPE_NAME='Default')
@override_settings(DOCBOW_PFWB_SENDMAIL_ATTACHED_FILE_EMAIL=EXPEDITION_EMAIL)
@@ -236,8 +254,9 @@ Coucou''', EXPEDITION_EMAIL, RECIPIENT_EMAIL, 'PJD', 'Mouais: monfichier.pdf')
class SendMailAttachedFileTestCase(TestCase):
def setUp(self):
self.pjd_filetype = FileType.objects.create(name='PJD', id=2)
- self.tabellio_doc_type = TabellioDocType.objects.create(filetype=self.pjd_filetype,
- tabellio_doc_type='PJD')
+ self.tabellio_doc_type = TabellioDocType.objects.create(
+ filetype=self.pjd_filetype, tabellio_doc_type='PJD'
+ )
self.expedition_user = User.objects.create(username='expedition', id=1)
self.to_user = User.objects.create(username='recipient', email=RECIPIENT_EMAIL, id=2)
self.to_list = MailingList.objects.create(name='ma liste')
@@ -269,15 +288,17 @@ class SendMailAttachedFileTestCase(TestCase):
@stderr_output('')
def test_attached_file1(self):
with tempfile.NamedTemporaryFile() as f:
- f.write(self.build_message(
- self.pjd_filetype,
- EXPEDITION_EMAIL,
- RECIPIENT_EMAIL,
- 'coucou',
- (('attached-file', 'content'),)))
+ f.write(
+ self.build_message(
+ self.pjd_filetype,
+ EXPEDITION_EMAIL,
+ RECIPIENT_EMAIL,
+ 'coucou',
+ (('attached-file', 'content'),),
+ )
+ )
f.flush()
- management.call_command('sendmail', RECIPIENT_EMAIL, file=f.name,
- sender=EXPEDITION_EMAIL)
+ management.call_command('sendmail', RECIPIENT_EMAIL, file=f.name, sender=EXPEDITION_EMAIL)
self.assertEqual(Document.objects.count(), 1)
document = Document.objects.get()
assert document.attached_files.count() == 1
@@ -288,6 +309,7 @@ class SendMailAttachedFileTestCase(TestCase):
assert document.to_list.count() == 0
assert document.to_user.get() == self.to_user
+
@override_settings(MEDIA_ROOT=MEDIA_ROOT)
class PushDocumentTestCase(TestCase):
def setUp(self):
@@ -295,6 +317,7 @@ class PushDocumentTestCase(TestCase):
def tearDown(self):
import shutil
+
shutil.rmtree(self.ged_dir)
def test_push_document1(self):
@@ -306,25 +329,23 @@ class PushDocumentTestCase(TestCase):
FROM_USERNAME = 'from_user'
FROM_FIRST_NAME = 'from_first_name'
FROM_LAST_NAME = 'from_last_name'
- self.from_user = User.objects.create(username=FROM_USERNAME,
- first_name=FROM_FIRST_NAME, last_name=FROM_LAST_NAME)
+ self.from_user = User.objects.create(
+ username=FROM_USERNAME, first_name=FROM_FIRST_NAME, last_name=FROM_LAST_NAME
+ )
self.to_user = User.objects.create(username='to_user')
self.filetype = FileType.objects.create(name='filetype')
- self.plone_filetype = PloneFileType.objects.create(filetype=self.filetype,
- plone_portal_type='plone-portal-type')
+ self.plone_filetype = PloneFileType.objects.create(
+ filetype=self.filetype, plone_portal_type='plone-portal-type'
+ )
DESCRIPTION = 'description'
- self.document = Document.objects.create(sender=self.from_user,
- filetype=self.filetype,
- comment=DESCRIPTION)
- self.attached_file = AttachedFile(name='attached-file',
- document=self.document, kind=None)
+ self.document = Document.objects.create(
+ sender=self.from_user, filetype=self.filetype, comment=DESCRIPTION
+ )
+ self.attached_file = AttachedFile(name='attached-file', document=self.document, kind=None)
CONTENT = 'content'
- self.attached_file.content.save('attached-file',
- ContentFile(CONTENT))
- pattern1 = '{0}-*-{1}.json'.format(self.document.id,
- self.attached_file.name)
- pattern2 = '{0}-*-{1}'.format(self.document.id,
- self.attached_file.name)
+ self.attached_file.content.save('attached-file', ContentFile(CONTENT))
+ pattern1 = '{0}-*-{1}.json'.format(self.document.id, self.attached_file.name)
+ pattern2 = '{0}-*-{1}'.format(self.document.id, self.attached_file.name)
files1 = glob(os.path.join(self.ged_dir, pattern1))
files2 = glob(os.path.join(self.ged_dir, pattern2))
assert len(files1) == 1
@@ -332,18 +353,18 @@ class PushDocumentTestCase(TestCase):
with open(files2[0]) as f:
assert f.read() == CONTENT
import json
+
with open(files1[0]) as f:
json_content = json.loads(f.read())
self.assertIsNotNone(json_content)
assert json_content['document_id'] == self.document.id
- assert json_content['plone_portal_type'] == \
- self.plone_filetype.plone_portal_type
- assert json_content['title'] == \
- force_text(self.filetype)
+ assert json_content['plone_portal_type'] == self.plone_filetype.plone_portal_type
+ assert json_content['title'] == force_text(self.filetype)
assert json_content['description'] == DESCRIPTION
- assert json_content['sender'] == \
- u'{0} {1} ({2})'.format(FROM_FIRST_NAME,
- FROM_LAST_NAME, FROM_USERNAME)
+ assert json_content['sender'] == u'{0} {1} ({2})'.format(
+ FROM_FIRST_NAME, FROM_LAST_NAME, FROM_USERNAME
+ )
+
@override_settings(MEDIA_ROOT=MEDIA_ROOT)
@override_settings(DOCBOW_PFWB_GED_DIRECTORY=None)
@@ -355,21 +376,21 @@ class ArchiveTestCase(TestCase):
FROM_USERNAME = 'from_user'
FROM_FIRST_NAME = 'from_first_name'
FROM_LAST_NAME = 'from_last_name'
- self.from_user = User.objects.create(username=FROM_USERNAME,
- first_name=FROM_FIRST_NAME, last_name=FROM_LAST_NAME)
+ self.from_user = User.objects.create(
+ username=FROM_USERNAME, first_name=FROM_FIRST_NAME, last_name=FROM_LAST_NAME
+ )
self.to_user = User.objects.create(username='to_user')
self.filetype = FileType.objects.create(name='filetype')
- self.plone_filetype = PloneFileType.objects.create(filetype=self.filetype,
- plone_portal_type='plone-portal-type')
+ self.plone_filetype = PloneFileType.objects.create(
+ filetype=self.filetype, plone_portal_type='plone-portal-type'
+ )
DESCRIPTION = 'description'
- self.document = Document.objects.create(sender=self.from_user,
- filetype=self.filetype,
- comment=DESCRIPTION)
- self.attached_file = AttachedFile(name='attached-file',
- document=self.document, kind=None)
+ self.document = Document.objects.create(
+ sender=self.from_user, filetype=self.filetype, comment=DESCRIPTION
+ )
+ self.attached_file = AttachedFile(name='attached-file', document=self.document, kind=None)
CONTENT = 'content'
- self.attached_file.content.save('attached-file',
- ContentFile(CONTENT))
+ self.attached_file.content.save('attached-file', ContentFile(CONTENT))
self.document.post()
def tearDown(self):
@@ -386,16 +407,18 @@ class ArchiveTestCase(TestCase):
management.call_command('archive2', self.archive_dir, 0)
l = glob.glob(os.path.join(self.archive_dir, '*'))
assert len(l) == 1
- self.assertTrue(l[0].split('T')[0],
- datetime.datetime.today().isoformat())
+ self.assertTrue(l[0].split('T')[0], datetime.datetime.today().isoformat())
archive_dir = os.path.join(self.archive_dir, l[0])
self.assertTrue(os.path.exists(os.path.join(archive_dir, 'doc')))
- self.assertTrue(os.path.exists(os.path.join(archive_dir, 'doc',
- str(self.document.id))))
- self.assertTrue(os.path.exists(os.path.join(archive_dir, 'doc',
- str(self.document.id), 'document.json')))
- self.assertTrue(os.path.exists(os.path.join(archive_dir, 'doc',
- str(self.document.id), 'attached_file_%s.json' %
- self.attached_file.id)))
- self.assertTrue(os.path.exists(os.path.join(archive_dir,
- 'journal.txt')))
+ self.assertTrue(os.path.exists(os.path.join(archive_dir, 'doc', str(self.document.id))))
+ self.assertTrue(
+ os.path.exists(os.path.join(archive_dir, 'doc', str(self.document.id), 'document.json'))
+ )
+ self.assertTrue(
+ os.path.exists(
+ os.path.join(
+ archive_dir, 'doc', str(self.document.id), 'attached_file_%s.json' % self.attached_file.id
+ )
+ )
+ )
+ self.assertTrue(os.path.exists(os.path.join(archive_dir, 'journal.txt')))
diff --git a/tests/pfwb/test_sync_tabellio.py b/tests/pfwb/test_sync_tabellio.py
index 98d75e7..540a694 100644
--- a/tests/pfwb/test_sync_tabellio.py
+++ b/tests/pfwb/test_sync_tabellio.py
@@ -11,7 +11,15 @@ from sqlalchemy_utils import database_exists, create_database, drop_database
from docbow_project.docbow.models import DocbowProfile, FileType, MailingList
from docbow_project.pfwb.models import TabellioDocType
from docbow_project.pfwb.tabellio import (
- Base, DBSession, TAdresse, TCom, TComppol, TPer, TPershistoline, TTypehistoper, TTypedoc
+ Base,
+ DBSession,
+ TAdresse,
+ TCom,
+ TComppol,
+ TPer,
+ TPershistoline,
+ TTypehistoper,
+ TTypedoc,
)
@@ -75,8 +83,13 @@ def create_pers(session, first_name, last_name, adresse, st='XX'):
def create_pershisto(session, pers, typehisto, desc_obj, fin=None):
new_id = get_new_id(session, TPershistoline)
res = TPershistoline(
- id=new_id, pers=pers.id, type=typehisto.id, description=desc_obj.id, st='XX',
- debut=datetime.now(), fin=fin
+ id=new_id,
+ pers=pers.id,
+ type=typehisto.id,
+ description=desc_obj.id,
+ st='XX',
+ debut=datetime.now(),
+ fin=fin,
)
session.add(res)
session.commit()
@@ -274,9 +287,7 @@ def test_create_commission(session, db, ministres_list, parl_list):
foo = MailingList.objects.get(name='Commission - foo')
bar = MailingList.objects.get(name='Commission - bar')
- user = User.objects.get(
- first_name='John', last_name='Doe', email='john@doe.be', username='john.doe'
- )
+ user = User.objects.get(first_name='John', last_name='Doe', email='john@doe.be', username='john.doe')
assert foo.members.count() == 1
assert user in foo.members.all()
assert bar.members.count() == 0
@@ -301,12 +312,8 @@ def test_diable_commission(session, db, ministres_list, parl_list):
def test_update_commission(session, db, ministres_list, parl_list):
commission = MailingList.objects.create(name='Commission - foo')
- user = User.objects.create(
- first_name='John', last_name='Doe', email='john@doe.be', username='john.doe'
- )
- old_user = User.objects.create(
- first_name='Old', last_name='Man', email='old@man.be', username='old.man'
- )
+ user = User.objects.create(first_name='John', last_name='Doe', email='john@doe.be', username='john.doe')
+ old_user = User.objects.create(first_name='Old', last_name='Man', email='old@man.be', username='old.man')
commission.members.add(user)
commission.members.add(old_user)
assert commission.members.count() == 2
@@ -342,9 +349,7 @@ def test_create_political(session, db, ministres_list, parl_list):
def test_desactivate_innactive_political(session, db, ministres_list, parl_list):
ml = MailingList.objects.create(name='Appartenance politique - xx')
- old_user = User.objects.create(
- first_name='Old', last_name='Man', email='old@man.be', username='old.man'
- )
+ old_user = User.objects.create(first_name='Old', last_name='Man', email='old@man.be', username='old.man')
ml.members.add(old_user)
assert ml.is_active
assert ml.members.count() == 1
@@ -367,9 +372,7 @@ def test_desactivate_innactive_political(session, db, ministres_list, parl_list)
def test_remove_member_from_political(session, db, ministres_list, parl_list):
ml = MailingList.objects.create(name='Appartenance politique - green')
- old_user = User.objects.create(
- first_name='Old', last_name='Man', email='old@man.be', username='old.man'
- )
+ old_user = User.objects.create(first_name='Old', last_name='Man', email='old@man.be', username='old.man')
ml.members.add(old_user)
assert ml.is_active
assert ml.members.count() == 1
@@ -395,11 +398,13 @@ def test_document_types(session, db, ministres_list, parl_list):
TabellioDocType.objects.create(filetype=ft, tabellio_doc_type='doc-x')
assert TabellioDocType.objects.count() == 1
- session.add_all([
- TTypedoc(id='doc-0', descr='foo', st='st', fno=True, fnodoc=True, listnum=True),
- TTypedoc(id='doc-1', descr='bar', st='st', fno=True, fnodoc=True, listnum=True),
- TTypedoc(id='doc-x', descr='new', st='st', fno=True, fnodoc=True, listnum=True)
- ])
+ session.add_all(
+ [
+ TTypedoc(id='doc-0', descr='foo', st='st', fno=True, fnodoc=True, listnum=True),
+ TTypedoc(id='doc-1', descr='bar', st='st', fno=True, fnodoc=True, listnum=True),
+ TTypedoc(id='doc-x', descr='new', st='st', fno=True, fnodoc=True, listnum=True),
+ ]
+ )
session.commit()
management.call_command('sync-tabellio', '--verbosity', '2')
diff --git a/tests/pfwbmellon/settings.py b/tests/pfwbmellon/settings.py
index f4b3255..10ca37c 100644
--- a/tests/pfwbmellon/settings.py
+++ b/tests/pfwbmellon/settings.py
@@ -9,8 +9,6 @@ MELLON_ADAPTER = ('docbow_project.pfwb.mellon_adapter.PFWBMellonAdapter',)
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
- 'TEST': {
- 'NAME': 'docbow-test-%s' % os.environ.get("BRANCH_NAME", "").replace('/', '-')[:63],
- },
+ 'TEST': {'NAME': 'docbow-test-%s' % os.environ.get("BRANCH_NAME", "").replace('/', '-')[:63],},
}
}
diff --git a/tests/pw/test_pw.py b/tests/pw/test_pw.py
index 9446592..b89c11a 100644
--- a/tests/pw/test_pw.py
+++ b/tests/pw/test_pw.py
@@ -16,6 +16,7 @@ from django.utils.six import StringIO
MEDIA_ROOT = tempfile.mkdtemp()
+
@contextmanager
def captured_output():
new_out, new_err = StringIO(), StringIO()
@@ -26,6 +27,7 @@ def captured_output():
finally:
sys.stdout, sys.stderr = old_out, old_err
+
class stderr_output(object):
def __init__(self, output):
self.output = output
@@ -37,8 +39,10 @@ class stderr_output(object):
ret = func(testcase, *args, **kwargs)
testcase.assertEqual(self.output, err.getvalue())
return ret
+
return f
+
class stdout_output(object):
def __init__(self, output):
self.output = output
@@ -50,19 +54,22 @@ class stdout_output(object):
ret = func(testcase, *args, **kwargs)
testcase.assertEqual(self.output, out.getvalue())
return ret
+
return f
+
from django.test import TestCase
from django.test.utils import override_settings
from django.core import management
from django.contrib.auth.models import User
-from docbow_project.docbow.models import (FileType, MailingList, Document)
+from docbow_project.docbow.models import FileType, MailingList, Document
EXPEDITION_EMAIL = 'expedition@example.com'
RECIPIENT_EMAIL = 'recipient@example.com'
PRIVATE_RECIPIENT_EMAIL = 'recipient-private@example.com'
+
class MessageFile(object):
def __init__(self, filetype, to_addr, from_addr, content, attached_files, headers={}):
self.filetype = filetype
@@ -116,10 +123,16 @@ class SendMailAttachedFileTestCase(TestCase):
@stderr_output('')
def test_attached_file_with_forced_sender(self):
- with MessageFile(self.pjd_filetype, 'whatthefuck@example.com', 'whatthefuck-too@example.com',
- 'coucou', (('attached-file', 'content'),)) as f:
- management.call_command('sendmail', RECIPIENT_EMAIL, file=f.name,
- sender=self.expedition_user.username)
+ with MessageFile(
+ self.pjd_filetype,
+ 'whatthefuck@example.com',
+ 'whatthefuck-too@example.com',
+ 'coucou',
+ (('attached-file', 'content'),),
+ ) as f:
+ management.call_command(
+ 'sendmail', RECIPIENT_EMAIL, file=f.name, sender=self.expedition_user.username
+ )
self.assertEqual(Document.objects.count(), 1)
document = Document.objects.get()
assert document.comment == 'coucou'
@@ -132,10 +145,17 @@ class SendMailAttachedFileTestCase(TestCase):
@stderr_output('')
def test_attached_file_with_forced_sender_and_private_header(self):
- with MessageFile(self.pjd_filetype, 'whatthefuck@example.com', 'whatthefuck-too@example.com',
- 'coucou', (('attached-file', 'content'),), headers={'Private': '1'}) as f:
- management.call_command('sendmail', RECIPIENT_EMAIL, file=f.name,
- sender=self.expedition_user.username)
+ with MessageFile(
+ self.pjd_filetype,
+ 'whatthefuck@example.com',
+ 'whatthefuck-too@example.com',
+ 'coucou',
+ (('attached-file', 'content'),),
+ headers={'Private': '1'},
+ ) as f:
+ management.call_command(
+ 'sendmail', RECIPIENT_EMAIL, file=f.name, sender=self.expedition_user.username
+ )
self.assertEqual(Document.objects.count(), 1)
document = Document.objects.get()
assert document.private is True
@@ -149,10 +169,16 @@ class SendMailAttachedFileTestCase(TestCase):
@stderr_output('')
def test_attached_file_with_forced_sender_and_private_email(self):
- with MessageFile(self.pjd_filetype, 'whatthefuck@example.com', 'whatthefuck-too@example.com',
- 'coucou', (('attached-file', 'content'),)) as f:
- management.call_command('sendmail', PRIVATE_RECIPIENT_EMAIL, file=f.name,
- sender=self.expedition_user.username)
+ with MessageFile(
+ self.pjd_filetype,
+ 'whatthefuck@example.com',
+ 'whatthefuck-too@example.com',
+ 'coucou',
+ (('attached-file', 'content'),),
+ ) as f:
+ management.call_command(
+ 'sendmail', PRIVATE_RECIPIENT_EMAIL, file=f.name, sender=self.expedition_user.username
+ )
self.assertEqual(Document.objects.count(), 1)
document = Document.objects.get()
assert document.private is True
@@ -171,7 +197,9 @@ def test_email_wrong_encoding(db, settings):
User.objects.create(username='recipient', email=RECIPIENT_EMAIL, id=2)
FileType.objects.create(name='QE-Question', id=2)
management.call_command(
- 'sendmail', RECIPIENT_EMAIL, file='tests/data/email-encoded-iso-8859-15-but-says-utf-8',
- sender=expedition_user.username
+ 'sendmail',
+ RECIPIENT_EMAIL,
+ file='tests/data/email-encoded-iso-8859-15-but-says-utf-8',
+ sender=expedition_user.username,
)
assert Document.objects.count() == 1
diff --git a/tests/settings.py b/tests/settings.py
index 4446f73..b242205 100644
--- a/tests/settings.py
+++ b/tests/settings.py
@@ -7,9 +7,7 @@ DOCBOW_PRIVATE_DOCUMENTS = True
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
- 'TEST': {
- 'NAME': 'docbow-test-%s' % os.environ.get("BRANCH_NAME", "").replace('/', '-')[:63],
- },
+ 'TEST': {'NAME': 'docbow-test-%s' % os.environ.get("BRANCH_NAME", "").replace('/', '-')[:63],},
}
}
diff --git a/tests/sso/settings.py b/tests/sso/settings.py
index 7d17791..3d98477 100644
--- a/tests/sso/settings.py
+++ b/tests/sso/settings.py
@@ -7,8 +7,6 @@ INSTALLED_APPS += ('mellon',)
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
- 'TEST': {
- 'NAME': 'docbow-test-%s' % os.environ.get("BRANCH_NAME", "").replace('/', '-')[:63],
- },
+ 'TEST': {'NAME': 'docbow-test-%s' % os.environ.get("BRANCH_NAME", "").replace('/', '-')[:63],},
}
}
diff --git a/tests/sso/test_profile.py b/tests/sso/test_profile.py
index 11d77f5..4f6d7e7 100644
--- a/tests/sso/test_profile.py
+++ b/tests/sso/test_profile.py
@@ -30,7 +30,6 @@ def user():
class MockResp(object):
-
def __init__(self, json=None, excp=None):
self._json = json
self._excp = excp
@@ -47,6 +46,7 @@ class MockResp(object):
def test_create_delegate_sso(a2settings, app, monkeypatch, users):
a2settings.AUTHENTIC_ROLE = 'roleuuid'
import docbow_project.docbow.utils
+
mock_resp1 = MockResp(json={'uuid': '1234'})
mock_resp2 = MockResp()
mock_post = mock.Mock(side_effect=[mock_resp1, mock_resp2])
@@ -89,8 +89,8 @@ def test_create_delegate_sso(a2settings, app, monkeypatch, users):
@pytest.mark.django_db
def test_create_delegate_a2_failed(a2settings, app, monkeypatch, users):
import docbow_project.docbow.utils
- mock_resp = MockResp(
- json={'errors': {'some': ['a2 error']}}, excp=requests.exceptions.RequestException())
+
+ mock_resp = MockResp(json={'errors': {'some': ['a2 error']}}, excp=requests.exceptions.RequestException())
mock_post = mock.Mock(return_value=mock_resp)
monkeypatch.setattr(docbow_project.docbow.utils.requests, 'post', mock_post)
@@ -110,6 +110,7 @@ def test_create_delegate_a2_failed(a2settings, app, monkeypatch, users):
@pytest.mark.django_db
def test_delete_delegate_sso(a2settings, client, monkeypatch, user):
import docbow_project.docbow.profile_views
+
mock_resp = MockResp(json={})
mock_delete = mock.Mock(return_value=mock_resp)
monkeypatch.setattr(docbow_project.docbow.profile_views.requests, 'delete', mock_delete)
@@ -124,12 +125,7 @@ def test_delete_delegate_sso(a2settings, client, monkeypatch, user):
mellon.models.UserSAMLIdentifier.objects.create(name_id='1234', issuer=issuer, user=delegate)
client.login(username='user', password='password')
- client.post(
- '/profile/',
- {
- 'delegate-delete-john.doe-1.x': True,
- }
- )
+ client.post('/profile/', {'delegate-delete-john.doe-1.x': True,})
assert not user.delegations_to.count()
call_args = mock_delete.call_args[1]
assert call_args['url'] == 'https://a2-url/api/users/1234'