ci: apply pre-commit hooks (#86370)

This commit is contained in:
Benjamin Dauvergne 2024-01-31 18:05:25 +01:00
parent f98e0560da
commit 229479409e
139 changed files with 1716 additions and 1830 deletions

View File

@ -1,11 +1,11 @@
#!/usr/bin/env python
import os.path
import time
import json
import os.path
import random
import time
import numpy
import random
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'docbow_project.settings')

24
debian/control vendored
View File

@ -2,32 +2,32 @@ Source: docbow
Maintainer: Benjamin Dauvergne <bdauvergne@entrouvert.com>
Section: python
Priority: optional
Build-Depends: python3-setuptools,
python3-all,
debhelper-compat (= 12),
Build-Depends: debhelper-compat (= 12),
dh-python,
openssl,
python3-all,
python3-django (>= 1:1.11),
python3-setuptools,
yelp-tools,
yelp-xsl
yelp-xsl,
Standards-Version: 3.9.6
Homepage: https://dev.entrouvert.org/projects/docbow
Package: docbow
Architecture: all
Suggests: postgresql
Depends: ${python3:Depends},
${misc:Depends},
Suggests: postgresql,
Depends: python3-bs4,
python3-django (>= 1:1.11),
python3-bs4,
python3-django-journal (>= 2.0.0),
python3-django-picklefield,
python3-django-tables2,
python3-requests,
python3-django-watson (>= 1.2.0),
python3-magic,
python3-psycopg2,
python3-django-watson (>= 1.2.0),
python3-requests,
uwsgi,
uwsgi-plugin-python3
Recommends: python3-django-mellon
uwsgi-plugin-python3,
${misc:Depends},
${python3:Depends},
Recommends: python3-django-mellon,
Description: Document Box Wallone

6
debian/dirs vendored
View File

@ -1,10 +1,10 @@
etc/docbow
usr/share/docbow/templates
etc/nginx/sites-available
usr/lib/docbow
usr/share/docbow/templates
var/lib/docbow/collectstatic
var/lib/docbow/media
var/lib/docbow/static
var/lib/docbow/collectstatic
var/lib/docbow/templates
var/run/docbow
var/log/docbow
var/run/docbow

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
import sys
import os
import sys
if __name__ == '__main__':
from django.core.management import execute_from_command_line

View File

@ -5,7 +5,4 @@ class AppConfig(django.apps.AppConfig):
name = 'docbow_project.docbow'
def ready(self):
from . import signals
default_app_config = 'docbow_project.docbow.AppConfig'
pass

View File

@ -1,8 +1,9 @@
import csv
from django.core.exceptions import PermissionDenied
from django.http import HttpResponse
from django.utils.encoding import force_str, force_text
from django.utils.translation import ugettext as _
from django.utils.encoding import force_str
from django.utils.translation import gettext as _
def export_as_csv(modeladmin, request, queryset):
@ -13,7 +14,7 @@ def export_as_csv(modeladmin, request, queryset):
raise PermissionDenied
opts = modeladmin.model._meta
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename=%s.csv' % force_text(opts).replace('.', '_')
response['Content-Disposition'] = 'attachment; filename=%s.csv' % force_str(opts).replace('.', '_')
writer = csv.writer(response)
field_names = [field.name for field in opts.fields]
m2m_field_names = [m2m_field.name for m2m_field in opts.many_to_many]
@ -21,11 +22,11 @@ def export_as_csv(modeladmin, request, queryset):
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_str(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))
value = ','.join(map(force_str, value.all()))
values.append(force_str(value))
writer.writerow(map(lambda x: force_str(x), values))
return response

View File

@ -1,28 +1,22 @@
# -*- coding: utf-8 -*-
import django.contrib.admin as admin
from django.utils.translation import ugettext as _
from django.contrib.auth import admin as auth_admin, models as auth_models
from django.conf import settings
from django.contrib.auth import admin as auth_admin
from django.contrib.auth import models as auth_models
from django.core.exceptions import PermissionDenied
from django.urls import reverse, NoReverseMatch
from django.conf.urls import url
from django.urls import NoReverseMatch, re_path, reverse
from django.utils.safestring import mark_safe
from django.utils.translation import gettext as _
try:
import thread
except ImportError:
import _thread as thread
import django_journal.admin
from docbow_project.docbow import models
from docbow_project.docbow import forms
from docbow_project.docbow import views
from docbow_project.docbow import notification
from docbow_project.docbow import actions
from docbow_project.docbow import auth_views
from docbow_project.docbow import actions, auth_views, forms, models, notification, views
TITLE = u"Plate-forme sécurisée d'échange de documents"
TITLE = "Plate-forme sécurisée d'échange de documents"
class DocbowAdminSite(admin.AdminSite):
@ -74,7 +68,7 @@ class MailingListAdmin(admin.ModelAdmin):
"""Show delete actions only if user has delete rights
Show activation actions only if user has rights to change mailing lists
"""
a = super(MailingListAdmin, self).get_actions(request)
a = super().get_actions(request)
if request.user.has_perm('docbow.delete_mailinglist'):
a['delete_selected'] = self.get_action('delete_selected')
if request.user.has_perm('docbow.change_mailinglist'):
@ -88,8 +82,8 @@ class AttachedFileAdmin(admin.ModelAdmin):
return {}
def get_urls(self):
urls = super(AttachedFileAdmin, self).get_urls()
attached_file_urls = [url(r'^(.+)/download/$', self.download)]
urls = super().get_urls()
attached_file_urls = [re_path(r'^(.+)/download/$', self.download)]
return attached_file_urls + urls
def download(self, request, object_id):
@ -139,17 +133,17 @@ class DocbowUserAdmin(auth_admin.UserAdmin):
inlines += [UserSAMLIdentifierInlineAdmin]
def get_groups(self, user):
return u', '.join(group.name for group in user.groups.all())
return ', '.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())
return ', '.join(_list.name for _list in user.mailing_lists.all())
get_lists.short_description = _('mailing lists')
def get_actions(self, request):
a = super(DocbowUserAdmin, self).get_actions(request)
a = super().get_actions(request)
if request.user.has_perm('auth.delete_docbowuser'):
a['delete_selected'] = self.get_action('delete_selected')
if request.user.has_perm('auth.change_docbowuser'):
@ -193,7 +187,7 @@ class InboxAdmin(MailboxAdmin):
def queryset(self, request):
'''Only show input mailboxes'''
qs = super(InboxAdmin, self).queryset(request)
qs = super().queryset(request)
qs = qs.filter(outbox=False)
return qs
@ -205,7 +199,7 @@ class OutboxAdmin(MailboxAdmin):
def queryset(self, request):
'''Only show output mailboxes'''
qs = super(OutboxAdmin, self).queryset(request)
qs = super().queryset(request)
qs = qs.filter(outbox=True)
return qs
@ -223,7 +217,7 @@ class AutomaticForwardingAdmin(admin.ModelAdmin):
def formfield_for_manytomany(self, db_field, request, **kwargs):
if db_field.name in ('originaly_to_user', 'forward_to_user'):
kwargs['queryset'] = models.non_guest_users()
return super(AutomaticForwardingAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
return super().formfield_for_foreignkey(db_field, request, **kwargs)
class FileTypeAttachedFileKindAdmin(admin.TabularInline):
@ -262,12 +256,12 @@ class NotificationAdmin(admin.ModelAdmin):
def object_link(self, obj):
if obj is not None:
url = u'{0}:{1}_{2}_change'.format(
url = '{}:{}_{}_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'<a href="{0}" class="external-link">{1}</a>'.format(url, obj)
return f'<a href="{url}" class="external-link">{obj}</a>'
except NoReverseMatch:
pass
return ''

View File

@ -1,4 +1,4 @@
class AppSettings(object):
class AppSettings:
__DEFAULTS = {
'PERSONAL_EMAIL': True,
'MOBILE_PHONE': True,
@ -26,20 +26,20 @@ class AppSettings(object):
@property
def DOCBOW_MENU(self):
from django.utils.translation import ugettext_noop
from django.utils.translation import gettext_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')),
('send-file-selector', gettext_noop('send-file_menu')),
('inbox', gettext_noop('inbox_menu')),
('outbox', gettext_noop('outbox_menu')),
('docbow_admin:index', gettext_noop('admin_menu')),
('profile', gettext_noop('profile_menu')),
('mailing-lists', gettext_noop('mailing-lists')),
('help', gettext_noop('help_menu')),
('contact', gettext_noop('contact_menu')),
],
)

View File

@ -33,7 +33,6 @@ class DelegationAuthBackend:
try:
import mellon.backends
class DocbowMellonAuthBackend(mellon.backends.SAMLBackend):
@ -47,7 +46,7 @@ try:
set_auth_hash_getter(user, delegate)
return user
except User.DoesNotExist:
return super(DocbowMellonAuthBackend, self).get_user(user_id)
return super().get_user(user_id)
except ImportError:
pass

View File

@ -1,44 +1,39 @@
from django.conf.urls import url
from django.contrib.auth import views as auth_views
from django.urls import reverse_lazy
from django.urls import path, re_path, reverse_lazy
from docbow_project.docbow import views
from docbow_project.docbow import forms
from docbow_project.docbow import auth_views as docbow_auth_views
from docbow_project.docbow import forms, views
urlpatterns = [
url(
r'^login/$', docbow_auth_views.login, {'template_name': 'registration/login.html'}, name='auth_login'
),
url(
r'^logout/$',
path('login/', docbow_auth_views.login, {'template_name': 'registration/login.html'}, name='auth_login'),
path(
'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/$',
path('password/change/', views.password_change, name='auth_password_change'),
path(
'password/change/done/',
auth_views.PasswordChangeDoneView.as_view(),
name='auth_password_change_done',
),
url(
r'^password/reset/$',
path(
'password/reset/',
auth_views.PasswordResetView.as_view(
success_url=reverse_lazy('auth_password_reset_done'),
form_class=forms.PasswordResetFormWithLogging,
),
name='auth_password_reset',
),
url(
re_path(
r'^password/reset/confirm/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>.+)/$',
auth_views.PasswordResetConfirmView.as_view(),
name='auth_password_reset_confirm',
),
url(
r'^password/reset/complete/$',
path(
'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'),
path('password/reset/done/', views.password_reset_done, name='auth_password_reset_done'),
]

View File

@ -5,7 +5,6 @@ from django.contrib.auth import views as auth_views
from django.http import HttpResponseRedirect
from django.shortcuts import resolve_url
if 'mellon' in settings.INSTALLED_APPS:
from mellon.utils import get_idps
else:

View File

@ -1,23 +1,23 @@
class FormWithRequestMixin(object):
class FormWithRequestMixin:
def get_form_kwargs(self, **kwargs):
kwargs = super(FormWithRequestMixin, self).get_form_kwargs(**kwargs)
kwargs = super().get_form_kwargs(**kwargs)
kwargs['request'] = self.request
return kwargs
class FormWithPrefixMixin(object):
class FormWithPrefixMixin:
# deprecated after Django 1.6
prefix = None
def get_form_kwargs(self, **kwargs):
kwargs = super(FormWithPrefixMixin, self).get_form_kwargs(**kwargs)
kwargs = super().get_form_kwargs(**kwargs)
kwargs['prefix'] = self.prefix
return kwargs
class FormWithPostTarget(FormWithPrefixMixin):
def get_form_kwargs(self, **kwargs):
kwargs = super(FormWithPostTarget, self).get_form_kwargs(**kwargs)
kwargs = super().get_form_kwargs(**kwargs)
if not self.is_post_target():
kwargs.pop('data', None)
kwargs.pop('files', None)

View File

@ -1,9 +1,9 @@
from functools import wraps
from django.shortcuts import redirect
from django.contrib import messages
from django.utils.translation import ugettext as _
from django.shortcuts import redirect
from django.utils.cache import patch_cache_control
from django.utils.translation import gettext as _
from django.views.decorators.cache import never_cache as old_never_cache

View File

@ -1,8 +1,7 @@
import re
from email.header import decode_header, make_header
from django.utils.encoding import force_text
from django.utils.encoding import force_str
# check spaces between encoded_words (and strip them)
sre = re.compile(r'\?=[ \t]+=\?')
@ -13,7 +12,7 @@ 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))
u = force_str(make_header(h))
return u

View File

@ -1,10 +1,10 @@
from django.contrib.auth.models import User
from django.forms import ValidationError, MultipleChoiceField
from django.utils.translation import ugettext as _
from django.forms import MultipleChoiceField, ValidationError
from django.utils.translation import gettext as _
from docbow_project.docbow import pyuca
from docbow_project.docbow.models import username, MailingList
from docbow_project.docbow.widgets import ForcedValueWidget, FilteredSelectMultiple
from docbow_project.docbow.models import MailingList, username
from docbow_project.docbow.widgets import FilteredSelectMultiple, ForcedValueWidget
def order_choices(choices):
@ -22,7 +22,7 @@ def order_field_choices(field):
print(field.choices)
class Func2Iter(object):
class Func2Iter:
'''Transform a generator producing function into an iterator'''
def __init__(self, func):
@ -40,7 +40,7 @@ class RecipientField(MultipleChoiceField):
self.user_qs = kwargs.pop('user_qs', User.objects.filter())
self.user_qs = self.user_qs.filter(is_active=True, delegations_by__isnull=True)
self.list_qs = kwargs.pop('list_qs', MailingList.objects.active())
super(RecipientField, self).__init__(*args, **kwargs)
super().__init__(*args, **kwargs)
self._choices = self.widget.choices = Func2Iter(self.get_recipients_choices)
def reset_choices(self):
@ -79,7 +79,7 @@ class RecipientField(MultipleChoiceField):
def clean(self, value):
'''Validate that the value is not empty.'''
value = super(RecipientField, self).clean(value)
value = super().clean(value)
if not value:
raise ValidationError(_(u'you must set at least one user recipient or one list recipient...'))
raise ValidationError(_('you must set at least one user recipient or one list recipient...'))
return value

View File

@ -1,60 +1,49 @@
import os.path
import hmac
import collections
import datetime
import hashlib
import hmac
import logging
import collections
import os.path
import urllib.parse
from django.forms import (
ModelForm,
Form,
Textarea,
EmailField,
CharField,
ModelChoiceField,
ModelMultipleChoiceField,
)
from django import forms
from django.contrib.auth.models import User
from django.utils.translation import ugettext as _
from django.contrib.admin.widgets import FilteredSelectMultiple as AdminFilteredSelectMultiple
from django.forms import ValidationError
from django.conf import settings
from django.contrib.admin.widgets import FilteredSelectMultiple as AdminFilteredSelectMultiple
from django.contrib.auth.forms import PasswordChangeForm, PasswordResetForm
from django.contrib.auth.models import User
from django.db.models.query import Q
from django.contrib.auth.forms import PasswordResetForm, PasswordChangeForm
from django.utils.encoding import force_text
from django.forms import CharField, EmailField, Form, ModelChoiceField, ModelForm, Textarea, ValidationError
from django.utils.encoding import force_str
from django.utils.translation import gettext as _
from django_journal import journal as django_journal
from docbow_project.docbow import app_settings, fields, models, notification, pyuca, widgets
from docbow_project.docbow.fields import RecipientField
from docbow_project.docbow.middleware import get_extra
from docbow_project.docbow.models import (
Document,
username,
MailingList,
Content,
AttachedFile,
AutomaticForwarding,
Content,
DocbowProfile,
non_guest_users,
is_guest,
Document,
FileTypeAttachedFileKind,
MailingList,
is_guest,
non_guest_users,
username,
)
from docbow_project.docbow.widgets import TextInpuWithPredefinedValues, JqueryFileUploadInput
from docbow_project.docbow.fields import RecipientField
from docbow_project.docbow.utils import a2_wscall, mime_types_to_extensions, truncate_filename
from docbow_project.docbow.validators import phone_normalize, validate_fr_be_phone
from docbow_project.docbow.middleware import get_extra
from docbow_project.docbow.utils import mime_types_to_extensions, truncate_filename, a2_wscall
from docbow_project.docbow import fields, app_settings, models, widgets
from docbow_project.docbow import notification, pyuca
from docbow_project.docbow.widgets import FilteredSelectMultiple
from docbow_project.docbow.widgets import (
FilteredSelectMultiple,
JqueryFileUploadInput,
TextInpuWithPredefinedValues,
)
logger = logging.getLogger(__name__)
class RecipientForm(object):
class RecipientForm:
"""
Base form mixin for forms containing a RecipienField, i.e. all
forms for sending documents.
@ -67,7 +56,7 @@ class RecipientForm(object):
if user_qs is None:
user_qs = non_guest_users()
list_qs = kwargs.pop('list_qs', MailingList.objects.active())
super(RecipientForm, self).__init__(*args, **kwargs)
super().__init__(*args, **kwargs)
self.fields['recipients'].user = user
self.fields['recipients'].user_qs = user_qs
self.fields['recipients'].list_qs = list_qs
@ -98,7 +87,7 @@ class ForwardingForm(RecipientForm, Form):
.order_by('last_name', 'first_name', 'username')
.distinct()
)
super(ForwardingForm, self).__init__(*args, **kwargs)
super().__init__(*args, **kwargs)
if len(delegations) > 1:
self.fields['sender'].queryset = delegations
self.fields['sender'].label_from_instance = lambda y: username(y)
@ -106,7 +95,7 @@ class ForwardingForm(RecipientForm, Form):
del self.fields['sender']
def clean(self):
cleaned_data = super(ForwardingForm, self).clean()
cleaned_data = super().clean()
if not cleaned_data.get('sender'):
cleaned_data['sender'] = self.default_sender
return cleaned_data
@ -150,9 +139,9 @@ class FileForm(RecipientForm, ModelForm):
initial['recipients'] = ['user-%s' % doc.sender.id]
if doc.extra_senders.exists():
initial['recipients'] += ['user-%s' % sender.pk for sender in doc.extra_senders.all()]
initial['comment'] = u'Re: ' + doc.comment
initial['comment'] = 'Re: ' + doc.comment
super(FileForm, self).__init__(*args, **kwargs)
super().__init__(*args, **kwargs)
self.content_fields = []
if self.attached_file_kinds:
insert_index = 2
@ -215,23 +204,23 @@ class FileForm(RecipientForm, ModelForm):
def clean(self):
'''Validate that there is at least one file attached to this mailing.'''
cleaned_data = super(FileForm, self).clean()
cleaned_data = super().clean()
for field, attached_file_kind in self.content_fields:
upload_id, upload_files = self.cleaned_data.get(field, (None, []))
max_files = attached_file_kind.cardinality
min_files = attached_file_kind.minimum
errors = []
if max_files and len(upload_files) > max_files:
errors.append(_(u'You must attach at most %d file(s).') % max_files)
errors.append(_('You must attach at most %d file(s).') % max_files)
if min_files and len(upload_files) < min_files:
errors.append(_(u'You must attach at least %d file(s).') % min_files)
errors.append(_('You must attach at least %d file(s).') % min_files)
for upload_file in upload_files:
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 = _('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)
@ -253,7 +242,7 @@ class FileForm(RecipientForm, ModelForm):
self.instance.reply_to = self.reply_to
if self.user != self.instance.sender:
self.instance.real_sender = username(self.user)
return super(FileForm, self).save(commit=commit)
return super().save(commit=commit)
def save_attachments(self):
"""Create a new AttachedFile object for each uploaded file; and attach
@ -327,7 +316,7 @@ class DelegationForm(Form):
self.user = kwargs.pop('user', None)
self.delegatees = kwargs.pop('delegatees', [])
self._request = kwargs.pop('request')
super(DelegationForm, self).__init__(*args, **kwargs)
super().__init__(*args, **kwargs)
qs = non_guest_users()
if self.user:
qs = qs.exclude(id=self.user.id)
@ -338,7 +327,7 @@ class DelegationForm(Form):
del self.fields['existing_user']
def clean(self):
cleaned_data = super(DelegationForm, self).clean()
cleaned_data = super().clean()
ok1 = bool(cleaned_data.get('first_name'))
ok2 = bool(cleaned_data.get('last_name'))
ok3 = bool(cleaned_data.get('email'))
@ -364,7 +353,7 @@ class DelegationForm(Form):
raise ValidationError(_('A delegation with the same email already exists'))
qs = non_guest_users().filter(email=email)
if qs.exists():
list_of_names = u', '.join([user.get_full_name() for user in qs])
list_of_names = ', '.join([user.get_full_name() for user in qs])
self.data = {}
self.is_bound = False
raise ValidationError(
@ -411,7 +400,7 @@ class AutomaticForwardingForm(ModelForm):
def clean(self):
'''Validate that the forwarding rule contains at least one recipient.'''
cleaned_data = super(AutomaticForwardingForm, self).clean()
cleaned_data = super().clean()
if not cleaned_data.get('forward_to_user') and not cleaned_data.get('forward_to_list'):
raise ValidationError(_('A forwarding rule must have at least one recipient, person or list.'))
return cleaned_data
@ -456,7 +445,7 @@ class ProfileForm(ModelForm):
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
force_bytes(settings.SECRET_KEY), force_str(date) + mobile_phone, hashlib.sha1
).hexdigest()
code = '%06d' % (int(code, 16) % 1000000)
key = '%s-code' % self.prefix if self.prefix else 'code'
@ -495,10 +484,11 @@ class ProfileForm(ModelForm):
import unicodedata
from django.contrib.auth.tokens import default_token_generator
from django.contrib.sites.shortcuts import get_current_site
from django.utils.http import urlsafe_base64_encode
from django.utils.encoding import force_bytes
from django.utils.http import urlsafe_base64_encode
def _unicode_ci_compare(s1, s2):
@ -605,7 +595,7 @@ class PasswordResetFormWithLogging(PasswordResetForm):
class PasswordChangeFormWithLogging(PasswordChangeForm):
def save(self, *args, **kwargs):
super(PasswordChangeFormWithLogging, self).save(*args, **kwargs)
super().save(*args, **kwargs)
django_journal.record('password-change', 'changed its email', user=self.user, ip=get_extra()['ip'])
@ -626,7 +616,7 @@ class FilterForm(forms.Form):
def __init__(self, *args, **kwargs):
request = kwargs.pop('request')
outbox = kwargs.pop('outbox', False)
super(FilterForm, self).__init__(*args, **kwargs)
super().__init__(*args, **kwargs)
self.fields['search_terms'].widget.attrs['data-boxtype'] = 'outbox' if outbox else 'inbox'
for field in ('sort', 'page'):
@ -634,7 +624,7 @@ class FilterForm(forms.Form):
self.fields[field] = forms.CharField(initial=request.GET.get(field), widget=forms.HiddenInput)
def clean(self):
cleaned_data = super(FilterForm, self).clean()
cleaned_data = super().clean()
if (
cleaned_data.get('not_before')
and cleaned_data.get('not_after')
@ -657,7 +647,7 @@ class EmailForm(ModelForm):
fields = ('email',)
def __init__(self, *args, **kwargs):
super(EmailForm, self).__init__(*args, **kwargs)
super().__init__(*args, **kwargs)
self.initial['email'] = ''
self.initial['old_email'] = self.instance.email
@ -668,7 +658,7 @@ class EmailForm(ModelForm):
return password
def clean(self):
cleaned_data = super(EmailForm, self).clean()
cleaned_data = super().clean()
email = cleaned_data.get('email')
email2 = cleaned_data.get('email2')
if email and email2 and email != email2:
@ -695,11 +685,11 @@ class NotificationPreferencesForm(Form):
for np in models.NotificationPreference.objects.filter(user=self.user):
if not np.value:
self.initials[np.filetype_id].remove(np.kind)
super(NotificationPreferencesForm, self).__init__(*args, **kwargs)
super().__init__(*args, **kwargs)
for filetype in self.filetypes:
key = 'filetype-%s' % filetype.id
self.fields[key] = forms.MultipleChoiceField(
label=force_text(filetype),
label=force_str(filetype),
choices=self.choices,
initial=self.initials[filetype.id],
widget=widgets.CheckboxMultipleSelect,

View File

@ -3,7 +3,7 @@ import locale
from django.contrib.auth.models import User
from django.core.management.base import BaseCommand, CommandError
from django.db import transaction
from django.utils.encoding import force_text
from django.utils.encoding import force_str
from docbow_project.docbow.models import MailingList
@ -17,7 +17,6 @@ def get_object(model, ref):
class Command(BaseCommand):
help = '''Create or update a list'''
def add_arguments(self, parser):
@ -42,7 +41,7 @@ class Command(BaseCommand):
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_str(options['ml_name'], locale_encoding)
)
try:
for l in options['add_list']:

View File

@ -1,11 +1,11 @@
from optparse import make_option
from django.contrib.auth.models import User, Group
from django.contrib.auth.models import Group, User
from django.core.management.base import BaseCommand, CommandError
from django.db import transaction
from django.utils.encoding import force_text
from django.utils.encoding import force_str
from docbow_project.docbow.models import MailingList, DocbowProfile
from docbow_project.docbow.models import DocbowProfile, MailingList
def get_object(model, ref):
@ -49,11 +49,11 @@ List and groups can be referred by name or by id.
raise CommandError('username argument is mandatory')
user, created = User.objects.get_or_create(username=args[0])
if options['first_name']:
user.first_name = force_text(options['first_name'], 'utf-8')
user.first_name = force_str(options['first_name'], 'utf-8')
if options['last_name']:
user.last_name = force_text(options['last_name'], 'utf-8')
user.last_name = force_str(options['last_name'], 'utf-8')
if options['email']:
user.email = force_text(options['email'], 'utf-8')
user.email = force_str(options['email'], 'utf-8')
if options['activate'] is not None:
user.is_active = options['activate']
if options['superuser'] is not None:
@ -78,8 +78,8 @@ List and groups can be referred by name or by id.
raise CommandError('group %r does not exist' % g)
profile, created = DocbowProfile.objects.get_or_create(user=user)
if options['mobile_phone']:
profile.mobile_phone = force_text(options['mobile_phone'], 'utf-8')
profile.mobile_phone = force_str(options['mobile_phone'], 'utf-8')
if options['personal_email']:
profile.personal_email = force_text(options['personal_email'], 'utf-8')
profile.personal_email = force_str(options['personal_email'], 'utf-8')
user.save()
profile.save()

View File

@ -1,17 +1,17 @@
import shutil
import csv
import datetime as dt
import os
import os.path
import datetime as dt
import shutil
import time
from django.core.management.base import BaseCommand, CommandError
import django.contrib.auth.models as auth_models
from django.db import transaction
from django.conf import settings
from django.core.management.base import BaseCommand, CommandError
from django.db import transaction
from ... import models
from ....log import models as log_models
from ... import models
class Command(BaseCommand):
@ -50,7 +50,7 @@ class Command(BaseCommand):
csv_handle.writerow(dict(zip(csv_handle.fieldnames, csv_handle.fieldnames)))
logs = log_models.LogLine.objects.all()
for log in logs:
d = dict([(header, getattr(log, header)) for header in headers])
d = {header: getattr(log, header) for header in headers}
d['timestamp'] = d['timestamp'].isoformat()
self.dict_to_utf8(d)
csv_handle.writerow(d)

View File

@ -1,4 +1,5 @@
from django.core.management.base import BaseCommand
from ... import models

View File

@ -1,11 +1,11 @@
from optparse import make_option
from django.core import serializers
from django.core.exceptions import ImproperlyConfigured
from django.core.management.base import BaseCommand, CommandError
from django.core import serializers
from django.db import router, DEFAULT_DB_ALIAS
from django.db import DEFAULT_DB_ALIAS, router
from django.utils.datastructures import SortedDict
from optparse import make_option
class Command(BaseCommand):
option_list = BaseCommand.option_list + (

View File

@ -1,11 +1,9 @@
import csv
from django.core.management.base import BaseCommand, CommandError
import django.contrib.auth.models as auth_models
from django.core.management.base import BaseCommand, CommandError
from django.db import transaction
from ... import models
class Command(BaseCommand):
args = '<directory>'

View File

@ -13,7 +13,7 @@ def valid_date(s):
try:
return date_to_aware_datetime(datetime.strptime(s, '%Y-%m-%d'))
except ValueError:
msg = "Not a valid date: '{0}'.".format(s)
msg = f"Not a valid date: '{s}'."
raise argparse.ArgumentTypeError(msg)

View File

@ -1,10 +1,10 @@
import sys
import locale
import sys
from optparse import make_option
from django.core.management.base import BaseCommand
from django.db import transaction
from django.utils.encoding import force_text
from django.utils.encoding import force_str
from ...models import MailingList
from ...unicodecsv import UnicodeWriter
@ -13,7 +13,7 @@ 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 = '| ' + ' | '.join('{0:>{1}}'.format(x, col_width[i]) for i, x in enumerate(line)) + ' |'
print(line)
@ -35,7 +35,7 @@ class Command(BaseCommand):
for mailing_list in mailing_lists:
tables.append(
map(
force_text,
force_str,
(
mailing_list.id,
mailing_list.name,

View File

@ -1,11 +1,11 @@
import sys
import locale
import sys
from optparse import make_option
from django.contrib.auth.models import User
from django.core.management.base import BaseCommand
from django.db import transaction
from django.utils.encoding import force_text
from django.utils.encoding import force_str
from ...models import DocbowProfile
from ...unicodecsv import UnicodeWriter
@ -14,7 +14,7 @@ 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 = '| ' + ' | '.join('{0:>{1}}'.format(x, col_width[i]) for i, x in enumerate(line)) + ' |'
print(line)
@ -55,7 +55,7 @@ class Command(BaseCommand):
personal_email = ''
tables.append(
map(
force_text,
force_str,
(
user.id,
user.username,

View File

@ -1,19 +1,19 @@
import csv
import os.path
from optparse import make_option
import unicodedata
import random
import sys
import unicodedata
from optparse import make_option
from django.core.management.base import BaseCommand, CommandError
from django.contrib.auth import models as auth_models
from django.utils.encoding import force_text
from django.core.management.base import BaseCommand, CommandError
from django.utils.encoding import force_str
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):
@ -25,11 +25,11 @@ def unicode_csv_reader(utf8_csv_data, dialect=csv.excel, **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]
yield [force_str(cell, 'utf-8') for cell in row]
def csv_to_list(s):
return filter(None, map(str.strip, s.split(u',')))
return filter(None, map(str.strip, s.split(',')))
# Utilise seulement des majuscules et des chiffres, sauf i,l et 1, O et 0
@ -73,22 +73,22 @@ class Command(BaseCommand):
data['username'] = username
if 'profil' not in data:
default_profiles = csv_to_list(','.join(map(force_text, options.get('profile', []))))
default_profiles = csv_to_list(','.join(map(force_str, options.get('profile', []))))
data['profil'] = default_profiles
else:
data['profil'] = csv_to_list(data['profil'])
if 'groupe' not in data:
default_groups = csv_to_list(','.join(map(force_text, options.get('group', []))))
default_groups = csv_to_list(','.join(map(force_str, options.get('group', []))))
data['groupe'] = default_groups
else:
data['groupe'] = csv_to_list(data['groupe'])
if not data.get('password'):
if options.get('password'):
data['password'] = force_text(options['password'], 'utf8')
data['password'] = force_str(options['password'], 'utf8')
elif options.get('generate_password', False):
data['password'] = force_text(create_password())
data['password'] = force_str(create_password())
def handle(self, *args, **options):
if len(args) == 0:

View File

@ -2,12 +2,12 @@ import locale
import os.path
from django.contrib.auth.models import User
from django.core.files import File
from django.core.management.base import BaseCommand, CommandError
from django.db import transaction
from django.core.files import File
from django.utils.encoding import force_text
from django.utils.encoding import force_str
from docbow_project.docbow.models import MailingList, FileType, Document, AttachedFile
from docbow_project.docbow.models import AttachedFile, Document, FileType, MailingList
def get_object(model, ref, name='name'):
@ -19,7 +19,6 @@ def get_object(model, ref, name='name'):
class Command(BaseCommand):
help = '''Send a document'''
def add_arguments(self, parser):
@ -37,27 +36,27 @@ 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_str(options['sender'], locale_encoding), 'username')
except User.DoesNotExist:
raise CommandError('user %r does not exist' % options['sender'])
to_lists = []
try:
for l in options.get('to_list') or []:
l = get_object(MailingList, force_text(l, locale_encoding))
l = get_object(MailingList, force_str(l, locale_encoding))
to_lists.append(l)
except MailingList.DoesNotExist:
raise CommandError('list %r does not exist' % l)
to_users = []
try:
for l in options.get('to_user') or []:
l = get_object(User, force_text(l, locale_encoding), 'username')
l = get_object(User, force_str(l, locale_encoding), 'username')
to_users.append(l)
except User.DoesNotExist:
raise CommandError('user %r does not exist' % l)
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_str(options['filetype'], locale_encoding))
except FileType.DoesNotExist:
raise CommandError('filetype %r does not exist' % options['filetype'])
if not to_users and not to_lists:
@ -73,6 +72,6 @@ class Command(BaseCommand):
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
name=force_str(arg, locale_encoding), content=File(open(arg)), document=document
)
document.post()

View File

@ -1,6 +1,6 @@
import threading
import logging
import sys
import threading
from django.utils.deprecation import MiddlewareMixin

View File

@ -1,16 +1,13 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import django.utils.timezone
from django.conf import settings
import docbow_project.docbow.models
import django.core.validators
import django.utils.timezone
import picklefield.fields
from django.conf import settings
from django.db import migrations, models
import docbow_project.docbow.models
class Migration(migrations.Migration):
dependencies = [
('auth', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
@ -465,7 +462,7 @@ class Migration(migrations.Migration):
),
migrations.AlterUniqueTogether(
name='filetypeattachedfilekind',
unique_together=set([('name', 'file_type')]),
unique_together={('name', 'file_type')},
),
migrations.AddField(
model_name='document',
@ -536,7 +533,7 @@ class Migration(migrations.Migration):
),
migrations.AlterUniqueTogether(
name='delegation',
unique_together=set([('by', 'to')]),
unique_together={('by', 'to')},
),
migrations.AddField(
model_name='automaticforwarding',

View File

@ -1,12 +1,7 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
from django.conf import settings
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('docbow', '0001_initial'),
]

View File

@ -1,11 +1,7 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('docbow', '0002_auto_20190711_1812'),
]

View File

@ -1,11 +1,7 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('docbow', '0003_auto_20200319_1129'),
]

View File

@ -1,12 +1,9 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.29 on 2020-07-21 12:30
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('docbow', '0004_external_identifier'),
]

View File

@ -1,13 +1,10 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.29 on 2020-12-10 14:33
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('docbow', '0005_soft_delete'),

View File

@ -1,12 +1,9 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.29 on 2021-02-24 12:49
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('docbow', '0006_extra_senders'),
]

View File

@ -1,11 +1,9 @@
# Generated by Django 3.2.16 on 2023-06-13 11:53
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('docbow', '0007_filetype_extra_senders'),
]

View File

@ -1,47 +1,47 @@
import os
import datetime as dt
import itertools
import random
import hashlib
import html
import itertools
import os
import random
import re
import time
import urllib.parse
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,
PositiveIntegerField,
)
from django.contrib.auth.models import User, Group
from django.conf import settings
from django.template.defaultfilters import slugify
from django.utils.translation import ugettext_lazy as _, pgettext_lazy
from django.urls import reverse
from picklefield.fields import PickledObjectField
from django.utils.html import strip_tags
from django.utils.timezone import now, utc
from django.contrib.auth.models import Group, User
from django.db.models import (
CASCADE,
BooleanField,
CharField,
DateTimeField,
EmailField,
FileField,
ForeignKey,
Manager,
ManyToManyField,
Model,
OneToOneField,
PositiveIntegerField,
PositiveSmallIntegerField,
Q,
TextField,
)
from django.forms import ValidationError
from django.utils.encoding import force_text
from django.template.defaultfilters import slugify
from django.urls import reverse
from django.utils.encoding import force_str
from django.utils.html import strip_tags
from django.utils.safestring import mark_safe
from django.utils.timezone import now, utc
from django.utils.translation import gettext_lazy as _
from django.utils.translation import pgettext_lazy
from django_journal import journal as django_journal
from docbow_project.docbow.validators import validate_phone
from docbow_project.docbow.utils import file_match_mime_types
from picklefield.fields import PickledObjectField
from docbow_project.docbow import app_settings
from docbow_project.docbow.utils import file_match_mime_types
from docbow_project.docbow.validators import validate_phone
DOCBOW_APP = _('docbow')
DOCBOW_APP = _('Docbow_App')
@ -74,7 +74,7 @@ class ContentManager(Manager):
return self.get(description=description)
class NameNaturalKey(object):
class NameNaturalKey:
"""Model mixin to export the name of a model as a natural key. The name
field MUST be unique."""
@ -178,7 +178,7 @@ def username(user):
if user.first_name or user.last_name:
d = dict(last_name='', first_name='')
d.update(user.__dict__)
return u'{last_name} {first_name}'.format(**d)
return '{last_name} {first_name}'.format(**d)
return user.username
@ -210,9 +210,7 @@ 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().get_query_set().select_related().prefetch_related('attached_files')
class Document(Model):
@ -278,7 +276,7 @@ class Document(Model):
kind = attached_file.kind
name = attached_file.filename()
url = attached_file.link()
links.append(u'<a href="%s">%s</a>' % (url, name))
links.append('<a href="%s">%s</a>' % (url, name))
if kind and kind.name != last_kind_name:
links[-1] = kind.name + '&nbsp;: ' + links[-1]
last_kind_name = kind.name
@ -292,11 +290,11 @@ class Document(Model):
def group_human_to(self):
'''Return a sorted list of display names for list recipients.'''
return sorted(map(force_text, self.to_list.all()))
return sorted(map(force_str, self.to_list.all()))
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_str, self.to_list.all())))
def recipients(self):
"""Return a comma separated sorted list of display names for all
@ -363,7 +361,7 @@ class Document(Model):
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:
lists = u', '.join(m.name for m in to_with_origins[user] if m != '--direct--')
lists = ', '.join(m.name for m in to_with_origins[user] if m != '--direct--')
if '--direct--' in to_with_origins[user]:
django_journal.record(
'delivery',
@ -481,11 +479,11 @@ class DocumentForwarded(Model):
def __str__(self):
if self.automatic:
return _(u'forwarded document {from_document} as {to_document} on {date} automatically').format(
return _('forwarded document {from_document} as {to_document} on {date} automatically').format(
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(
return _('forwarded document {from_document} as {to_document} on {date}').format(
from_document=self.from_document, to_document=self.to_document, date=self.date
)
@ -498,7 +496,7 @@ def list_to_csv(l, mapping_func=None):
"""
if mapping_func:
l = map(mapping_func, l)
return u', '.join(map(force_text, l))
return ', '.join(map(force_str, l))
class AutomaticForwarding(Model):
@ -655,7 +653,7 @@ class Delegation(Model):
unique_together = (('by', 'to'),)
def __str__(self):
return u'delegation from {0}:{0.id} to {1}:{1.id}'.format(self.by, self.to)
return 'delegation from {0}:{0.id} to {1}:{1.id}'.format(self.by, self.to)
@property
def guest_delegate(self):
@ -747,7 +745,7 @@ class Mailbox(Model):
verbose_name_plural = _('Mailboxes')
def __str__(self):
return _(u'mailbox entry {id} of user {user}:{user.id} created on ' u'{date} for {document}').format(
return _('mailbox entry {id} of user {user}:{user.id} created on ' '{date} for {document}').format(
id=self.id, user=self.owner, date=self.date, document=self.document
)
@ -802,7 +800,7 @@ class SendingLimitation(Model):
def __str__(self):
return _(
u'sending limitation for list {mailing_list} to filetypes' u'{filetypes} and lists {lists}'
'sending limitation for list {mailing_list} to filetypes' '{filetypes} and lists {lists}'
).format(
mailing_list=self.mailing_list,
filetypes=list_to_csv(self.filetypes.all()),
@ -836,8 +834,8 @@ class DocbowProfile(Model):
def __str__(self):
return _(
u'docbow profile of {user}:{user.id} with mobile phone '
u'{mobile_phone} and personal email {personal_email}'
'docbow profile of {user}:{user.id} with mobile phone '
'{mobile_phone} and personal email {personal_email}'
).format(user=self.user, mobile_phone=self.mobile_phone, personal_email=self.personal_email)
@ -881,7 +879,7 @@ class Notification(Model):
ordering = ('-id',)
def __str__(self):
return _(u'notification {0}:{1}').format(self.kind, self.id)
return _('notification {0}:{1}').format(self.kind, self.id)
class NotificationPreference(Model):
@ -916,13 +914,13 @@ class DocumentAdapter(watson.SearchAdapter):
yield attached_file.name
def get_title(self, obj):
return u' '.join(self.gather_strings(obj))[:1000]
return ' '.join(self.gather_strings(obj))[:1000]
def get_description(self, obj):
return u' '.join(self.gather_strings(obj))
return ' '.join(self.gather_strings(obj))
def get_content(self, obj):
return u''
return ''
watson.register(Document, DocumentAdapter)

View File

@ -2,19 +2,18 @@ import importlib
import logging
from django.conf import settings
from django.template.loader import render_to_string, TemplateDoesNotExist
from django.core.mail import EmailMultiAlternatives
from django.utils.translation import ugettext_lazy as _
from django.utils.encoding import force_text
from django.template.loader import TemplateDoesNotExist, render_to_string
from django.utils.encoding import force_str
from django.utils.translation import gettext_lazy as _
from django_journal import journal as django_journal
from docbow_project.docbow import models
from docbow_project.docbow import app_settings
from docbow_project.docbow import app_settings, models
logger = logging.getLogger(__name__)
class BaseNotifier(object):
class BaseNotifier:
def __init__(self):
# accumulate preferences of users first
self.filter = set()
@ -106,7 +105,7 @@ class SMSNotifier(BaseNotifier):
body_template = 'docbow/sms-notification_{kind}_body.txt'
def __init__(self):
super(SMSNotifier, self).__init__()
super().__init__()
self.mobile_phones = dict()
def process(self, notification):
@ -175,7 +174,7 @@ def process_notifications():
notifier.process(notification)
except Exception as e:
failures.append(
u'Exception %r when handling with notifier %r' % (force_text(e), notifier.__class__)
'Exception %r when handling with notifier %r' % (force_str(e), notifier.__class__)
)
logger.exception(
'Exception when handling notification %r with notifier %r', notification, notifier
@ -203,5 +202,5 @@ def process_notifications():
'error',
'unable to finish sending ' 'notification with notifier {notifier}, error: {error}',
notifier=notifier.__class__,
error=force_text(e),
error=force_str(e),
)

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
#
# w.c.s. - web application for online forms
# Copyright (C) 2005-2013 Entr'ouvert
@ -27,8 +26,7 @@ except ImportError:
ET = None
from django.utils.encoding import force_text
from django.utils.encoding import force_str
OFFICE_NS = 'urn:oasis:names:tc:opendocument:xmlns:office:1.0'
TABLE_NS = 'urn:oasis:names:tc:opendocument:xmlns:table:1.0'
@ -36,7 +34,7 @@ TEXT_NS = 'urn:oasis:names:tc:opendocument:xmlns:text:1.0'
XLINK_NS = 'http://www.w3.org/1999/xlink'
class Workbook(object):
class Workbook:
def __init__(self, encoding='utf-8'):
self.sheets = []
self.encoding = encoding
@ -83,14 +81,14 @@ class Workbook(object):
z.close()
class WorkSheet(object):
class WorkSheet:
def __init__(self, workbook, name):
self.cells = {}
self.name = name
self.workbook = workbook
def write(self, row, column, value, hint=None):
if not row in self.cells:
if row not in self.cells:
self.cells[row] = {}
self.cells[row][column] = WorkCell(self, value, hint=hint)
@ -109,10 +107,10 @@ class WorkSheet(object):
return root
class WorkCell(object):
class WorkCell:
def __init__(self, worksheet, value, hint=None):
if type(value) is not str:
value = force_text(value, 'utf-8')
value = force_str(value, 'utf-8')
self.value = value
self.worksheet = worksheet
self.hint = hint

View File

@ -1,24 +1,16 @@
import urllib.parse
from django.shortcuts import redirect
from django.views.generic.edit import UpdateView, FormView
from django.views.generic.base import TemplateResponseMixin, View
from django.contrib import messages
from django.contrib.auth.models import User
from django.core.exceptions import ImproperlyConfigured
from django.utils.translation import ugettext as _
from django.http import HttpResponseRedirect
from django.db.transaction import atomic
from django.http import HttpResponseRedirect
from django.utils.translation import gettext as _
from django.views.generic.base import TemplateResponseMixin, View
from django.views.generic.edit import FormView, UpdateView
from django_journal.models import Journal
import requests
from docbow_project.docbow import models
from docbow_project.docbow import forms
from docbow_project.docbow import cbv
from docbow_project.docbow import utils
from docbow_project.docbow import app_settings
from docbow_project.docbow import app_settings, cbv, forms, models, utils
class ProfileView(cbv.FormWithRequestMixin, cbv.FormWithPostTarget, UpdateView):
@ -38,7 +30,7 @@ class ProfileView(cbv.FormWithRequestMixin, cbv.FormWithPostTarget, UpdateView):
def form_valid(self, form):
self.request.record('update-profile', 'modified its profile', **form.cleaned_data)
return super(ProfileView, self).form_valid(form)
return super().form_valid(form)
class DelegateView(cbv.FormWithPostTarget, FormView):
@ -48,7 +40,7 @@ class DelegateView(cbv.FormWithPostTarget, FormView):
prefix = 'delegate'
def __init__(self, *args, **kwargs):
super(DelegateView, self).__init__(*args, **kwargs)
super().__init__(*args, **kwargs)
def add_journal_to_delegations(self, delegations):
delegations__to = [delegation.to for delegation in delegations]
@ -75,7 +67,7 @@ class DelegateView(cbv.FormWithPostTarget, FormView):
return qs
def get_form_kwargs(self, **kwargs):
kwargs = super(DelegateView, self).get_form_kwargs(**kwargs)
kwargs = super().get_form_kwargs(**kwargs)
kwargs['user'] = self.request.user
kwargs['delegatees'] = [delegation.to for delegation in self.delegations]
kwargs['request'] = self.request
@ -109,7 +101,6 @@ class DelegateView(cbv.FormWithPostTarget, FormView):
# delete guest accounts
if delegation.guest_delegate:
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(
@ -135,17 +126,17 @@ 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 f'delegate-delete-{username}.x' in self.request.POST:
return True
return False
@atomic
def post(self, request, *args, **kwargs):
if 'delegate-create' in request.POST:
return super(DelegateView, self).post(request, *args, **kwargs)
return super().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 f'delegate-delete-{username}.x' in self.request.POST:
return self.delete(delegation)
return self.get(request, *args, **kwargs)
@ -226,10 +217,10 @@ class DelegateView(cbv.FormWithPostTarget, FormView):
request.record(
'create-delegation', 'created delegation to ' 'user {delegated}', delegated=delegate_user
)
return super(DelegateView, self).form_valid(form)
return super().form_valid(form)
def get_context_data(self, **kwargs):
ctx = super(DelegateView, self).get_context_data(**kwargs)
ctx = super().get_context_data(**kwargs)
ctx['delegations'] = self.delegations
ctx['received_delegations'] = self.request.user.delegations_by.all()
ctx['delegate_to_existing_user'] = app_settings.DELEGATE_TO_EXISTING_USER
@ -248,10 +239,10 @@ class PasswordChangeView(cbv.FormWithPostTarget, FormView):
def form_valid(self, form):
messages.info(self.request, _('Password changed'))
form.save()
return super(PasswordChangeView, self).form_valid(form)
return super().form_valid(form)
def get_form_kwargs(self, **kwargs):
kwargs = super(PasswordChangeView, self).get_form_kwargs(**kwargs)
kwargs = super().get_form_kwargs(**kwargs)
kwargs['user'] = self.request.user
return kwargs
@ -268,7 +259,7 @@ 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)
return super(EmailView, self).form_valid(form)
return super().form_valid(form)
class NotificationPreferenceView(cbv.FormWithPostTarget, cbv.FormWithRequestMixin, FormView):
@ -280,16 +271,16 @@ class NotificationPreferenceView(cbv.FormWithPostTarget, cbv.FormWithRequestMixi
def form_valid(self, form):
form.save()
messages.info(self.request, _('Notification preferences saved'))
return super(NotificationPreferenceView, self).form_valid(form)
return super().form_valid(form)
def get_context_data(self, **kwargs):
ctx = super(NotificationPreferenceView, self).get_context_data(**kwargs)
ctx = super().get_context_data(**kwargs)
ctx['mobile_phone'] = app_settings.MOBILE_PHONE
ctx['mobile_phone_paragraph'] = _(
u'If You would like to receive a SMS alert each '
u'time your inbox receives a document, provide your '
u'mobile phone number. If you do not fill this field '
u'you won\'t receive any SMS alert'
'If You would like to receive a SMS alert each '
'time your inbox receives a document, provide your '
'mobile phone number. If you do not fill this field '
'you won\'t receive any SMS alert'
)
return ctx
@ -312,7 +303,7 @@ class FullProfileView(TemplateResponseMixin, View):
if models.is_guest(request.user):
self.subviews = filter(lambda s: s[0] != 'delegate_form', self.subviews)
print(self.subviews)
return super(FullProfileView, self).dispatch(request, *args, **kwargs)
return super().dispatch(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
ctx = {}

View File

@ -72,7 +72,6 @@ class Trie:
class Collator:
def __init__(self, filename):
self.table = Trie()
self.load(filename)
@ -109,7 +108,6 @@ class Collator:
self.table.add(integer_points, collElements)
def sort_key(self, string):
collation_elements = []
lookup_key = [ord(ch) for ch in string]

View File

@ -1,13 +1,13 @@
from django.contrib.auth import models as auth_models
from django.contrib.auth.models import User
from django.contrib.auth.signals import user_logged_in, user_logged_out
from django.db.models.signals import post_save as db_post_save, m2m_changed
from django.contrib.auth import models as auth_models
from django.utils.translation import ugettext_noop as N_
from django.db.models.signals import m2m_changed
from django.db.models.signals import post_save as db_post_save
from django.dispatch import receiver
from django.utils.translation import gettext_noop as N_
from django_journal import journal as django_journal
from docbow_project.docbow import models
from docbow_project.docbow import middleware
from docbow_project.docbow import middleware, models
def logged_in_handler(sender, request, user, **kwargs):

View File

@ -1,22 +1,21 @@
import logging
import json
from django.utils.http import urlencode
import logging
from urllib.request import urlopen
from django.conf import settings
from django.utils.encoding import force_text
from django.utils.encoding import force_str
from django.utils.http import urlencode
from django_journal import journal as django_journal
logger = logging.getLogger(__name__)
class OVHSMSCarrier(object):
class OVHSMSCarrier:
URL = 'https://www.ovh.com/cgi-bin/sms/http2sms.cgi'
SMS_CLASS = 1
def send_sms(self, to, message, sms_class=None, no_stop=True):
payload = force_text(message).encode('utf-8')
payload = force_str(message).encode('utf-8')
sms_class = sms_class or self.SMS_CLASS
to = ','.join([t.replace('+', '00') for t in to])
params = {

View File

@ -1,10 +1,6 @@
# -*- coding: utf-8 -*-
from django.utils.translation import ugettext_lazy as _
from django.utils.safestring import mark_safe
import django_tables2 as tables
from django.utils.safestring import mark_safe
from django.utils.translation import gettext_lazy as _
from docbow_project.docbow import models
@ -72,7 +68,6 @@ class OutboxBaseTable(tables.Table):
class OutboxTrashTable(OutboxBaseTable):
restore = tables.TemplateColumn(
template_name='docbow/outbox_restore_column.html', orderable=False, verbose_name=_('Restore')
)
@ -133,7 +128,7 @@ class InboxCsvTable(tables.Table):
class InboxBaseTable(tables.Table):
seen = tables.BooleanColumn(accessor='seen', yesno=u' ,✔', verbose_name=' ', orderable=False)
seen = tables.BooleanColumn(accessor='seen', yesno=' ,✔', 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(
@ -167,7 +162,6 @@ class InboxBaseTable(tables.Table):
class InboxTrashTable(InboxBaseTable):
restore = tables.TemplateColumn(
template_name='docbow/inbox_restore_column.html', orderable=False, verbose_name=_('Restore')
)

View File

@ -1,10 +1,9 @@
from django.template.defaultfilters import slugify
from django import template
from django.template.defaultfilters import slugify
from django.urls import reverse
from django.utils.translation import ugettext as _
from django.utils.translation import gettext as _
from .. import views, models, app_settings, sql
from .. import app_settings, models, sql, views
register = template.Library()

View File

@ -1,11 +1,12 @@
# copied from http://djangosnippets.org/snippets/993/
# Author: simon
import csv
from django.utils.encoding import force_str, force_text
from io import StringIO
from django.utils.encoding import force_str
class UnicodeWriter(object):
class UnicodeWriter:
"""
Like UnicodeDictWriter, but takes lists rather than dictionaries.
@ -35,7 +36,7 @@ class UnicodeWriter(object):
self.writer.writerow([force_str(s).encode('utf-8') for s in row])
# Fetch UTF-8 output from the queue ...
data = self.queue.getvalue()
data = force_text(data, 'utf-8')
data = force_str(data, 'utf-8')
# ... and reencode it into the target encoding
data = data.encode(self.encoding)
# write to the target stream
@ -71,9 +72,9 @@ class UnicodeDictWriter(UnicodeWriter):
"""
def __init__(self, f, fields, dialect=csv.excel_tab, encoding='utf-16', **kwds):
super(UnicodeDictWriter, self).__init__(f, dialect, encoding, **kwds)
super().__init__(f, dialect, encoding, **kwds)
self.fields = fields
def writerow(self, drow):
row = [drow.get(field, '') for field in self.fields]
super(UnicodeDictWriter, self).writerow(row)
super().writerow(row)

View File

@ -1,16 +1,17 @@
from django.conf.urls import url
from django.urls import re_path
import docbow_project.docbow.upload_views
urlpatterns = [
url(
re_path(
r'^(?P<transaction_id>[a-zA-Z0-9-]+)/(?P<file_kind>[0-9]+)/$',
docbow_project.docbow.upload_views.upload,
name='upload',
),
url(r'^(?P<transaction_id>[a-zA-Z0-9-]+)/$', docbow_project.docbow.upload_views.upload, name='upload'),
url(
re_path(
r'^(?P<transaction_id>[a-zA-Z0-9-]+)/$', docbow_project.docbow.upload_views.upload, name='upload'
),
re_path(
r'^(?P<transaction_id>[a-zA-Z0-9-]+)/(?P<filename>[^/]+)$',
docbow_project.docbow.upload_views.upload_file,
name='uploaded',

View File

@ -1,18 +1,17 @@
# -*- encoding: utf-8 -*-
import os
import json
import os
from django.views.decorators.csrf import csrf_exempt
from django.urls import reverse
from django.core.files.storage import DefaultStorage
from django.core.files import File
from django.http import HttpResponse, Http404
from django.core.files.storage import DefaultStorage
from django.http import Http404, HttpResponse
from django.shortcuts import get_object_or_404
from django.utils.encoding import force_text
from django.utils.translation import ugettext_lazy as _
from django.urls import reverse
from django.utils.encoding import force_str
from django.utils.translation import gettext_lazy as _
from django.views.decorators.csrf import csrf_exempt
from .models import FileTypeAttachedFileKind
from . import app_settings
from .models import FileTypeAttachedFileKind
def get_paths_for_id(upload_id):
@ -41,7 +40,7 @@ def get_data_for_id(upload_id):
def response_mimetype(request):
if 'application/json' in request.META['HTTP_ACCEPT']:
if 'application/json' in request.headers['accept']:
return 'application/json'
else:
return 'text/plain'
@ -52,7 +51,7 @@ class JSONResponse(HttpResponse):
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)
super().__init__(content, mimetype, *args, **kwargs)
@csrf_exempt
@ -78,23 +77,23 @@ 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_str(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)})
data.append({'name': uploaded_file.name, 'error': force_str(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)})
data.append({'name': uploaded_file.name, 'error': force_str(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_str(message)})
continue
path = os.path.join('upload', str(transaction_id), uploaded_file.name)
filename = storage.save(path, uploaded_file)

View File

@ -1,104 +1,103 @@
from django.conf import settings
from django.conf.urls import url, include
from django.urls import include, path, re_path
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'),
path('', docbow_project.docbow.views.homepage, name='homepage'),
path('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<document_id>\d+)/$',
path('inbox/', docbow_project.docbow.views.inbox_view, name='inbox'),
path('inbox/trash/', docbow_project.docbow.views.inbox_trash_view, name='inbox-trash'),
path(
'inbox_by_document/<int:document_id>/',
docbow_project.docbow.views.inbox_by_document,
name='inbox-by-document-message',
),
url(
r'^inbox/(?P<mailbox_id>\d+)/$',
path(
'inbox/<int:mailbox_id>/',
docbow_project.docbow.views.message,
name='inbox-message',
kwargs={'outbox': False},
),
url(
r'^inbox/(?P<mailbox_id>\d+)/delete/$',
path(
'inbox/<int:mailbox_id>/delete/',
docbow_project.docbow.views.delete,
name='inbox-message-delete',
),
url(
r'^inbox/(?P<doc_id>\d+)/restore/$',
path(
'inbox/<int:doc_id>/restore/',
docbow_project.docbow.views.restore,
name='inbox-message-restore',
kwargs={'outbox': False},
),
url(
re_path(
r'^inbox/(?P<mailbox_id>\d+)/(?P<attached_file>\d+)/.*$',
docbow_project.docbow.views.message_attached_file,
name='inbox-message-attached-file',
),
url(
r'^inbox/(?P<mailbox_id>\d+)/allfiles/$',
path(
'inbox/<int:mailbox_id>/allfiles/',
docbow_project.docbow.views.message_all_files,
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'),
path('inbox/csv', docbow_project.docbow.views.inbox_csv, name='inbox-csv'),
path('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<mailbox_id>\d+)/$',
path('outbox/', docbow_project.docbow.views.outbox_view, name='outbox'),
path('outbox/trash/', docbow_project.docbow.views.outbox_trash_view, name='outbox-trash'),
path(
'outbox/<int:mailbox_id>/',
docbow_project.docbow.views.message,
name='outbox-message',
kwargs={'outbox': True},
),
url(
r'^outbox/(?P<mailbox_id>\d+)/delete/$',
path(
'outbox/<int:mailbox_id>/delete/',
docbow_project.docbow.views.delete,
name='outbox-message-delete',
kwargs={'outbox': True},
),
url(
r'^outbox/(?P<doc_id>\d+)/restore/$',
path(
'outbox/<int:doc_id>/restore/',
docbow_project.docbow.views.restore,
name='outbox-message-restore',
kwargs={'outbox': True},
),
url(
re_path(
r'^outbox/(?P<mailbox_id>\d+)/(?P<attached_file>\d+)/.*$',
docbow_project.docbow.views.message_attached_file,
name='outbox-message-attached-file',
kwargs={'outbox': True},
),
url(
r'^outbox/(?P<mailbox_id>\d+)/allfiles/$',
path(
'outbox/<int:mailbox_id>/allfiles/',
docbow_project.docbow.views.message_all_files,
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<file_type_id>\d+)/$', docbow_project.docbow.views.send_file, name='send-file'),
url(r'^help/$', docbow_project.docbow.views.help, name='help'),
url(r'^help/(?P<pagename>[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<username>.*)/$', 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'),
path('outbox/csv', docbow_project.docbow.views.outbox_csv, name='outbox-csv'),
path('outbox/ods', docbow_project.docbow.views.outbox_ods, name='outbox-ods'),
path('send_file/', docbow_project.docbow.views.send_file_selector, name='send-file-selector'),
path('send_file/<int:file_type_id>/', docbow_project.docbow.views.send_file, name='send-file'),
path('help/', docbow_project.docbow.views.help, name='help'),
re_path(r'^help/(?P<pagename>[a-zA-Z0-9-/\.]+)$', docbow_project.docbow.views.help, name='help'),
path('contact/', docbow_project.docbow.views.contact, name='contact'),
path('logout/', docbow_project.docbow.views.logout, name='logout'),
path('delegate/', docbow_project.docbow.views.delegate, name='delegate'),
path('upload/', include('docbow_project.docbow.upload_urls')),
re_path(r'^su/(?P<username>.*)/$', docbow_project.docbow.views.su, {'redirect_url': '/'}),
re_path(r'^mailing-lists/', docbow_project.docbow.views.mailing_lists, name='mailing-lists'),
re_path(r'^search-inbox/', docbow_project.docbow.views.search_inbox, name='search-inbox'),
re_path(r'^search-outbox/', docbow_project.docbow.views.search_outbox, name='search-outbox'),
]
for custom in ('docbow_project.pfwb', 'docbow_project.pw'):
if custom in settings.INSTALLED_APPS:
urlpatterns += [
url(r'^', include('%s.urls' % custom)),
path('', include('%s.urls' % custom)),
]
if 'mellon' in settings.INSTALLED_APPS:
urlpatterns.append(url(r'^accounts/mellon/', include('mellon.urls')))
urlpatterns.append(path('accounts/mellon/', include('mellon.urls')))

View File

@ -1,15 +1,15 @@
import os.path
import mimetypes
from itertools import count
import datetime
import mimetypes
import os.path
from itertools import count
import requests
from django.contrib.auth.models import User
from django.contrib.auth.tokens import default_token_generator
from django.urls import reverse
from django.utils import timezone
from django.utils.encoding import force_bytes
from django.utils.http import urlsafe_base64_encode
import requests
from docbow_project.docbow import app_settings
@ -125,7 +125,7 @@ def a2_wscall(url, method, json=None):
err_desc = str(e)
try:
json_data = resp.json()
except Exception as e:
except Exception:
pass
if err and json_data and 'errors' in json_data:
errors = json_data['errors']

View File

@ -2,10 +2,10 @@ import re
from django.core.validators import RegexValidator
validate_phone = RegexValidator('^\+\d+$')
validate_fr_be_phone = RegexValidator('^\+(?:33[67]\d{8}|324\d{8})$')
validate_phone = RegexValidator(r'^\+\d+$')
validate_fr_be_phone = RegexValidator(r'^\+(?:33[67]\d{8}|324\d{8})$')
def phone_normalize(phone_number):
'''Remove usual separators from phone number.'''
return re.sub('[\.\-\s]', '', phone_number)
return re.sub(r'[\.\-\s]', '', phone_number)

View File

@ -1,71 +1,66 @@
import smtplib
from itertools import count, chain
import socket
import os.path
import operator
import datetime
import operator
import os.path
import smtplib
import tempfile
import zipfile
from itertools import chain
from django.contrib.auth.decorators import login_required
from django.core.files.base import File
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.db.models.expressions import RawSQL
from django.db.models.query import Q
from django.contrib.auth.models import User
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.core.files.base import File
from django.core.mail import EmailMessage
from django.utils.translation import ugettext as _, ugettext_noop as N_, ungettext
from django.db.models.query import Q
from django.forms.forms import NON_FIELD_ERRORS
from django.http import Http404, HttpResponse, HttpResponseForbidden, HttpResponseRedirect, JsonResponse
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse
from django.utils.encoding import force_str
from django.utils.timezone import now
from django.views.generic.list import MultipleObjectMixin, ListView
from django.views.generic.base import View, RedirectView
from django.views.decorators.debug import sensitive_post_parameters
from django.utils.translation import gettext as _
from django.utils.translation import gettext_noop as N_
from django.utils.translation import ngettext
from django.views.decorators.cache import never_cache
from django.views.decorators.debug import sensitive_post_parameters
from django.views.decorators.http import require_http_methods
from django.utils.encoding import force_text
from django.views.generic.base import RedirectView, View
from django.views.generic.list import ListView, MultipleObjectMixin
try:
from BeautifulSoup import BeautifulSoup
except ImportError:
from bs4 import BeautifulSoup
import django_tables2.views as tables_views
import watson.search as watson
from docbow_project.docbow import app_settings, profile_views, sql, tables, unicodecsv
from docbow_project.docbow.decorators import as_delegate
from docbow_project.docbow.forms import (
FileForm,
AnonymousContactForm,
ContactForm,
ForwardingForm,
FileForm,
FilterForm,
ForwardingForm,
)
from docbow_project.docbow.models import (
Mailbox,
AttachedFile,
SendingLimitation,
MailingList,
is_guest,
DeletedDocument,
Document,
FileType,
DeletedDocument,
Mailbox,
MailingList,
SeenDocument,
SendingLimitation,
is_guest,
non_guest_users,
username,
)
from docbow_project.docbow.decorators import as_delegate
from docbow_project.docbow import tables
from docbow_project.docbow import app_settings
from docbow_project.docbow import unicodecsv
from docbow_project.docbow import profile_views
from docbow_project.docbow import sql
from docbow_project.docbow.utils import date_to_aware_datetime
gettext_noop = lambda x: x
@ -103,7 +98,7 @@ def get_document(request, mailbox_id, outbox):
)
class Row(object):
class Row:
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
@ -394,7 +389,7 @@ def message(request, mailbox_id, outbox=False):
document=forwarded_document.from_document,
new_document=forwarded_document.to_document,
)
msg = ungettext(
msg = ngettext(
'Document forwarded to {recipients_count} ' 'recipient.',
'Document forwarded to {recipients_count} ' 'recipients.',
recipients_count,
@ -435,7 +430,7 @@ def get_help_content(pagename):
t.name = 'h4'
for t in page.findAll('h1'):
t.name = 'h3'
return force_text(page)
return force_str(page)
@login_required
@ -496,7 +491,7 @@ def contact(request, template='docbow/contact.html', form_class=AnonymousContact
reply_to=reply_to,
phone=cleaned_data.get('phone_number'),
)
except (smtplib.SMTPException, socket.error):
except (smtplib.SMTPException, OSError):
import logging
logging.getLogger(__name__).exception('unable to send mail to administrators')
@ -565,8 +560,8 @@ def restore(request, doc_id, outbox=False):
return redirect(return_view)
from django.contrib.auth import SESSION_KEY, BACKEND_SESSION_KEY
from django import http
from django.contrib.auth import BACKEND_SESSION_KEY, SESSION_KEY
def su(request, username, redirect_url='/'):
@ -619,7 +614,7 @@ def password_reset_done(request):
return redirect('auth_login')
class DateFilterMixinView(object):
class DateFilterMixinView:
def get_filter_form(self):
if not hasattr(self, '_form'):
if 'clear' in self.request.GET:
@ -630,12 +625,12 @@ class DateFilterMixinView(object):
return self._form
def get_context_data(self, **kwargs):
context = super(DateFilterMixinView, self).get_context_data(**kwargs)
context = super().get_context_data(**kwargs)
context['filter_form'] = self.get_filter_form()
return context
def get_queryset(self):
qs = super(DateFilterMixinView, self).get_queryset()
qs = super().get_queryset()
filter_form = self.get_filter_form()
if filter_form.is_valid():
not_before = filter_form.cleaned_data.get('not_before')
@ -656,11 +651,11 @@ class DateFilterMixinView(object):
return qs
class ExtraContextMixin(object):
class ExtraContextMixin:
extra_ctx = {}
def get_context_data(self, **kwargs):
context = super(ExtraContextMixin, self).get_context_data(**kwargs)
context = super().get_context_data(**kwargs)
context.update(self.extra_ctx)
return context
@ -679,9 +674,9 @@ def get_related_users(request):
return User.objects.filter(pk__in=request.session['related_users'])
class MailboxQuerysetMixin(object):
class MailboxQuerysetMixin:
def get_queryset(self):
qs = super(MailboxQuerysetMixin, self).get_queryset()
qs = super().get_queryset()
if hasattr(self.request.user, 'delegate'):
qs = qs.filter(private=False)
@ -692,14 +687,14 @@ class MailboxQuerysetMixin(object):
return self._qs
def get_context_data(self, **kwargs):
ctx = super(MailboxQuerysetMixin, self).get_context_data(**kwargs)
ctx = super().get_context_data(**kwargs)
ctx['related_users'] = get_related_users(self.request)
return ctx
class TrashMailboxQuerysetMixin(object):
class TrashMailboxQuerysetMixin:
def get_queryset(self):
qs = super(TrashMailboxQuerysetMixin, self).get_queryset()
qs = super().get_queryset()
if not hasattr(self, '_qs'):
self._qs = sql.get_trash_documents(
qs, get_related_users(self.request), self.request.user, self.outbox
@ -707,7 +702,7 @@ class TrashMailboxQuerysetMixin(object):
return self._qs
def get_context_data(self, **kwargs):
ctx = super(TrashMailboxQuerysetMixin, self).get_context_data(**kwargs)
ctx = super().get_context_data(**kwargs)
ctx['related_users'] = get_related_users(self.request)
return ctx
@ -739,7 +734,7 @@ class TrashMailboxView(ExtraContextMixin, TrashMailboxQuerysetMixin, tables_view
return get_table_kwargs()
class CSVMultipleObjectMixin(object):
class CSVMultipleObjectMixin:
mapping = ()
filename = ''
@ -750,7 +745,7 @@ class CSVMultipleObjectMixin(object):
value = operator.attrgetter(attribute)(mailbox)
if callable(value):
value = value()
return force_text(value)
return force_str(value)
def get_row(self, mailbox):
for column in self.mapping:
@ -783,7 +778,7 @@ class ODSMultipleObjectMixin(CSVMultipleObjectMixin):
rows = chain(((0, self.get_header()),), enumerate(self.get_rows(), 1))
for i, row in rows:
for j, cell in enumerate(row):
sheet.write(i, j, force_text(cell))
sheet.write(i, j, force_str(cell))
workbook.save(response)
return response
@ -859,7 +854,7 @@ class ODSOutboxView(ODSMailboxView, CSVOutboxView):
outbox_ods = ODSOutboxView.as_view()
class DeleteDocumentsView(object):
class DeleteDocumentsView:
def post(self, request, *args, **kwargs):
documents = None
selection = request.POST.get('selection', '')
@ -947,7 +942,7 @@ class SendFileSelectorView(ListView):
model = FileType
def get_queryset(self):
qs = super(SendFileSelectorView, self).get_queryset()
qs = super().get_queryset()
limitations = get_filetype_limitation(self.request.user)
if limitations:
return limitations

View File

@ -1,16 +1,23 @@
import uuid
import re
import uuid
from django.forms import Textarea, MultiWidget, Select, HiddenInput, FileInput, SelectMultiple
from django.utils.safestring import mark_safe
from django.conf import settings
from django.forms import (
CheckboxSelectMultiple,
FileInput,
HiddenInput,
MultiWidget,
Select,
SelectMultiple,
Textarea,
)
from django.template.loader import render_to_string
from django.forms import CheckboxSelectMultiple
from .upload_views import get_files_for_id
from django.utils.safestring import mark_safe
from docbow_project.docbow import app_settings
from .upload_views import get_files_for_id
class TextInpuWithPredefinedValues(MultiWidget):
CLIENT_CODE = '''
@ -27,20 +34,20 @@ class TextInpuWithPredefinedValues(MultiWidget):
def __init__(self, attrs=None, choices=[]):
widget_list = (Select(attrs=attrs, choices=choices), Textarea(attrs=attrs))
super(TextInpuWithPredefinedValues, self).__init__(widget_list, attrs)
super().__init__(widget_list, attrs)
def decompress(self, value):
return ['---', value]
def value_from_datadict(self, data, files, name):
select, text_input = super(TextInpuWithPredefinedValues, self).value_from_datadict(data, files, name)
select, text_input = super().value_from_datadict(data, files, name)
if text_input or select == '---':
return text_input
else:
return select
def render(self, name, value, attrs=None, renderer=None):
output = super(TextInpuWithPredefinedValues, self).render(name, value, attrs)
output = super().render(name, value, attrs)
return output + mark_safe(self.CLIENT_CODE % {'name': name})
@ -50,7 +57,7 @@ class MultiFileInput(FileInput):
"""
def __init__(self, attrs=None):
super(MultiFileInput, self).__init__(attrs)
super().__init__(attrs)
self.attrs['multiple'] = 'true'
def value_from_datadict(self, data, files, name):
@ -61,7 +68,6 @@ class MultiFileInput(FileInput):
class JqueryFileUploadFileInput(MultiFileInput):
template_name = 'docbow/upload-multiwidget.html'
class Media:
@ -82,7 +88,7 @@ class JqueryFileUploadFileInput(MultiFileInput):
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)
super().__init__(*args, **kwargs)
def _get_context(self, name):
return {
@ -98,7 +104,7 @@ class JqueryFileUploadFileInput(MultiFileInput):
}
def get_context(self, name, value, attrs):
context = super(JqueryFileUploadFileInput, self).get_context(name, value, attrs)
context = super().get_context(name, value, attrs)
context['widget'].update(self._get_context(name))
return context
@ -129,7 +135,7 @@ class JqueryFileUploadInput(MultiWidget):
attrs=attrs, extensions=extensions, attached_file_kind=attached_file_kind
),
)
super(JqueryFileUploadInput, self).__init__(widget_list, attrs)
super().__init__(widget_list, attrs)
def decompress(self, value):
# map python value to widget contents
@ -147,7 +153,7 @@ class JqueryFileUploadInput(MultiWidget):
If a regular hidden_id is present, use it to find uploaded files,
otherwise return an empty list
"""
upload_id, file_input = super(JqueryFileUploadInput, self).value_from_datadict(data, files, name)
upload_id, file_input = super().value_from_datadict(data, files, name)
if file_input:
pass
elif JqueryFileUploadInput.upload_id_re.match(upload_id):
@ -168,7 +174,7 @@ 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().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}
@ -177,7 +183,7 @@ class JqueryFileUploadInput(MultiWidget):
class ForcedValueWidget(SelectMultiple):
def __init__(self, attrs=None, format=None, value=None, display_value=''):
super(ForcedValueWidget, self).__init__(attrs)
super().__init__(attrs)
self.display_value = display_value
self.value = value
@ -186,7 +192,7 @@ class ForcedValueWidget(SelectMultiple):
def render(self, name, value, attrs=None, renderer=None):
return mark_safe(
u'<div class="selector"><span class="display-value">%s</span></div>' % self.display_value
'<div class="selector"><span class="display-value">%s</span></div>' % self.display_value
)
@ -211,7 +217,7 @@ class FilteredSelectMultiple(SelectMultiple):
def __init__(self, verbose_name, is_stacked, attrs=None, choices=()):
self.verbose_name = verbose_name
self.is_stacked = is_stacked
super(FilteredSelectMultiple, self).__init__(attrs, choices)
super().__init__(attrs, choices)
def render(self, name, value, attrs=None, *args, **kwargs):
if attrs is None:
@ -224,15 +230,15 @@ class FilteredSelectMultiple(SelectMultiple):
if 'required' in attrs:
del attrs['required']
output = [super(FilteredSelectMultiple, self).render(name, value, attrs, *args, **kwargs)]
output.append(u'<script type="text/javascript">addEvent(window, "load", function(e) {')
output = [super().render(name, value, attrs, *args, **kwargs)]
output.append('<script type="text/javascript">addEvent(window, "load", function(e) {')
# TODO: "id_" is hard-coded here. This should instead use the correct
# API to determine the ID dynamically.
output.append(
u'SelectFilter.init("id_%s", "%s", %s, "%s"); });</script>\n'
'SelectFilter.init("id_%s", "%s", %s, "%s"); });</script>\n'
% (name, self.verbose_name.replace('"', '\\"'), int(self.is_stacked), settings.STATIC_URL)
)
return mark_safe(u''.join(output))
return mark_safe(''.join(output))
CheckboxMultipleSelect = CheckboxSelectMultiple

View File

@ -1,8 +1,8 @@
from django import template
from django.utils.timezone import localtime, get_default_timezone
from django.template.defaultfilters import date
from django.utils.html import escape
from django.utils.safestring import mark_safe
from django.template.defaultfilters import date
from django.utils.timezone import localtime
from .. import utils
@ -12,7 +12,7 @@ register = template.Library()
@register.filter
def humandate(dt):
full_dt = date(dt, 'SHORT_DATE_FORMAT')
s = u'<span title="{0}">{1}</span>'.format(escape(full_dt), escape(utils.datetime2human(dt)))
s = f'<span title="{escape(full_dt)}">{escape(utils.datetime2human(dt))}</span>'
return mark_safe(s)
@ -20,7 +20,7 @@ def humandate(dt):
def humantime(dt):
dt = localtime(dt)
full_dt = date(dt, 'SHORT_DATETIME_FORMAT')
s = u'<span title="{0}">{1}</span>'.format(
s = '<span title="{}">{}</span>'.format(
escape(full_dt), escape(utils.datetime2human(dt, include_time=True))
)
return mark_safe(s)

View File

@ -1,8 +1,8 @@
import datetime
from django.utils.translation import pgettext
from django.utils.timezone import localtime, get_default_timezone
from django.template.defaultfilters import date
from django.utils.timezone import get_default_timezone, localtime
from django.utils.translation import pgettext
def datetime2human(dt, include_time=False, days_limit=7):

View File

@ -5,7 +5,4 @@ class AppConfig(django.apps.AppConfig):
name = 'docbow_project.pfwb'
def ready(self):
from . import signals
default_app_config = 'docbow_project.pfwb.AppConfig'
pass

View File

@ -1,7 +1,4 @@
# -*- coding: utf-8 -*-
class AppSettings(object):
class AppSettings:
'''Thanks django-allauth'''
__DEFAULTS = dict(

View File

@ -1,12 +1,12 @@
import shutil
import sys
import datetime as dt
import os
import os.path
import datetime as dt
import shutil
import sys
from django.core import serializers
from django.core.management.base import BaseCommand
from django.db import transaction
from django.core import serializers
from django.utils.encoding import force_str
from django.utils.timezone import now
from django_journal.models import Journal

View File

@ -1,30 +1,28 @@
from datetime import datetime as dt
import sys
import mailbox
import email
import email.errors
import email.utils
import email.header
import email.utils
import logging
import mailbox
import re
import sys
import time
from datetime import datetime as dt
from urllib.request import urlopen
from django.conf import settings
from django.core.management.base import BaseCommand
import django.contrib.auth.models as auth_models
from django.conf import settings
from django.core.files.base import ContentFile
from django.core.exceptions import MultipleObjectsReturned
from django.utils.timezone import utc, make_aware
from django.utils.encoding import force_text
from django.template.defaultfilters import slugify
from docbow_project.docbow import models, utils
from docbow_project.docbow.email_utils import u2u_decode
from django_journal.journal import record
from django.core.management.base import BaseCommand
from django.db.transaction import atomic
from django.template.defaultfilters import slugify
from django.utils.encoding import force_str
from django.utils.timezone import utc
from django_journal.journal import record
from docbow_project.docbow import app_settings as docbow_app_settings
from docbow_project.docbow import models, utils
from docbow_project.docbow.email_utils import u2u_decode
from docbow_project.pfwb import app_settings
logger = logging.getLogger('docbow.mail_interface')
@ -67,7 +65,7 @@ In case of failure the following return value is returned:
mail = email.message_from_binary_file(open(options['file'], 'rb'))
else:
mail = email.message_from_binary_file(sys.stdin.buffer)
except email.errors.MessageParseError as e:
except email.errors.MessageParseError:
self.error('7.7.1 Error parsing message', exit_code=1)
if settings.SENDMAIL_DEBUG_MBOX:
try:
@ -77,7 +75,7 @@ In case of failure the following return value is returned:
logger.exception('mbox exception')
try:
self.handle_mail(mail, (options['recipient'],), **options)
except Exception as e:
except Exception:
logger.exception('Unknown exception')
self.error('7.7.1 Internal error when handling the mail', exit_code=5)
@ -103,7 +101,7 @@ In case of failure the following return value is returned:
if m:
result = []
for content, encoding in email.header.decode_header(filename):
result.append(force_text(content, encoding or 'ascii'))
result.append(force_str(content, encoding or 'ascii'))
return ''.join(result)
else:
return filename
@ -124,7 +122,7 @@ In case of failure the following return value is returned:
attachments = []
recipients = []
mailing_list_recipients = []
description = u''
description = ''
from_email = email.utils.parseaddr(options['sender'])[1]
if not from_email:
self.error('7.7.1 No sender', exit_code=8)
@ -154,7 +152,7 @@ In case of failure the following return value is returned:
self.error('7.7.1 Mail is missing a subject', exit_code=2)
try:
subject = u2u_decode(subject)
except Exception as e:
except Exception:
self.error('7.7.1 The subject cannot be decoded', exit_code=3)
try:
filetype = models.FileType.objects.get(name=subject)
@ -194,7 +192,7 @@ In case of failure the following return value is returned:
'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)
description = force_str(part.get_payload(decode=True), charset)
if filename:
filename = self.decode_filename(filename)
@ -213,7 +211,7 @@ In case of failure the following return value is returned:
self.error('7.7.1 Mail is missing a subject', exit_code=2)
try:
subject = u2u_decode(subject)
except Exception as e:
except Exception:
self.error('7.7.1 The subject cannot be decoded', exit_code=3)
try:
name = subject.split(':', 1)[1].strip()

View File

@ -3,9 +3,11 @@ from django.contrib.auth.models import User
from django.core.management.base import BaseCommand
from django.db import transaction
from django.template.defaultfilters import slugify
from sqlalchemy import create_engine, engine as sqla_engine, or_
from sqlalchemy import create_engine
from sqlalchemy import engine as sqla_engine
from sqlalchemy import or_
from docbow_project.docbow.models import MailingList, DocbowProfile, FileType
from docbow_project.docbow.models import DocbowProfile, FileType, MailingList
from docbow_project.pfwb.models import TabellioDocType
from docbow_project.pfwb.tabellio import DBSession, TAdresse, TCom, TComppol, TPer, TPershistoline, TTypedoc
@ -108,7 +110,6 @@ class Command(BaseCommand):
TPershistoline.type.in_(['P_CMPL', 'M_MINT']),
TPershistoline.fin.isnot(None),
):
last_name, first_name = pers.nom, pers.prenom
username = get_username(last_name, first_name)
@ -143,7 +144,6 @@ class Command(BaseCommand):
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)
@ -158,7 +158,6 @@ class Command(BaseCommand):
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,
@ -190,12 +189,12 @@ class Command(BaseCommand):
deputy_users.append(user)
# update mailing lists
if not user in parl_list.members.all():
if user not in parl_list.members.all():
parl_list.members.add(user)
parl_list.save()
# keep track of its political group, to be used later
if not comppol in comppols:
if comppol not in comppols:
comppols[comppol] = []
comppols[comppol].append(user)
@ -207,7 +206,7 @@ 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='Appartenance politique - %s' % comppol
)
# remove members of the list that should no longer be in there
for member in maillist.members.all():
@ -220,8 +219,8 @@ class Command(BaseCommand):
# 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]
inactive_comppols = ['Appartenance politique - %s' % comppol.abbr for comppol in query]
comppol_names = ['Appartenance politique - %s' % comppol for comppol in comppols]
for maillist in MailingList.objects.filter(name__startswith='Appartenance politique -').exclude(
name__in=comppol_names
):
@ -238,7 +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='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
@ -267,12 +266,15 @@ class Command(BaseCommand):
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(
for (
pers,
pers_histo,
addr,
) in session.query(TPer, TPershistoline, TAdresse).filter(
TPer.st == 'S_MINISTRE',
TPer.prenom.isnot(None),
TPer.id == TPershistoline.pers,
@ -282,7 +284,6 @@ class Command(BaseCommand):
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)
@ -294,7 +295,7 @@ class Command(BaseCommand):
ministres_users.append(user)
# update mailing lists
if not user in ministres_list.members.all():
if user not in ministres_list.members.all():
ministres_list.members.add(user)
ministres_list.save()

View File

@ -1,4 +1,5 @@
from django.conf import settings
from docbow_project.docbow.models import DocbowProfile
@ -15,7 +16,6 @@ def get_tabellio_id(saml_attributes):
try:
import mellon.adapters
import mellon.models
@ -29,10 +29,10 @@ try:
except DocbowProfile.DoesNotExist:
pass
return super(PFWBMellonAdapter, self).lookup_by_attributes(idp, saml_attributes)
return super().lookup_by_attributes(idp, saml_attributes)
def provision(self, user, idp, saml_attributes):
super(PFWBMellonAdapter, self).provision(user, idp, saml_attributes)
super().provision(user, idp, saml_attributes)
tabellio_id = get_tabellio_id(saml_attributes)
if tabellio_id:
try:

View File

@ -1,11 +1,7 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('docbow', '0001_initial'),
]

View File

@ -1,5 +1,5 @@
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from ..docbow.models import FileType

View File

@ -1,9 +1,9 @@
import os.path
import json
import datetime
import json
import os.path
from django.db.models import signals
from django.utils.encoding import force_text
from django.utils.encoding import force_str
from ..docbow.models import AttachedFile
from . import app_settings, models
@ -19,12 +19,12 @@ def push_document(signal, sender, instance, **kwargs):
plone_file_type = document.filetype.plonefiletype
except models.PloneFileType.DoesNotExist:
return
tpl = u'{sender.first_name} {sender.last_name} ({sender.username})'
tpl = '{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),
'title': force_str(document.filetype),
'description': document.comment,
'reception_date': document.date.isoformat().split('.')[0],
'sender': sender,

View File

@ -3,12 +3,11 @@ https://pypi.org/project/sqlacodegen/
"""
from sqlalchemy import ARRAY, Boolean, Column, Date, DateTime, ForeignKey, Index, Integer, Text, TEXT
from sqlalchemy import ARRAY, TEXT, Boolean, Column, Date, DateTime, ForeignKey, Index, Integer, Text
from sqlalchemy.dialects.postgresql import TSVECTOR
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, sessionmaker
Base = declarative_base()
DBSession = sessionmaker()

View File

@ -3,6 +3,3 @@ import django.apps
class AppConfig(django.apps.AppConfig):
name = 'docbow_project.pw'
default_app_config = 'docbow_project.pw.AppConfig'

View File

@ -1,28 +1,28 @@
from datetime import datetime as dt
import sys
import mailbox
import email
import email.errors
import email.utils
import email.header
import email.utils
import logging
import mailbox
import re
import sys
import time
from datetime import datetime as dt
from django.conf import settings
from django.core.management.base import BaseCommand
import django.contrib.auth.models as auth_models
from django.core.files.base import ContentFile
from django.conf import settings
from django.core.exceptions import MultipleObjectsReturned
from django.utils.encoding import force_text
from django.utils.timezone import utc, make_aware
from django.template.defaultfilters import slugify
from django.core.files.base import ContentFile
from django.core.management.base import BaseCommand
from django.db.models.query import Q
from django.db.transaction import atomic
from django.template.defaultfilters import slugify
from django.utils.encoding import force_str
from django.utils.timezone import utc
from django_journal.journal import error_record, record
from docbow_project.docbow import models, utils
from docbow_project.docbow.email_utils import u2u_decode
from django_journal.journal import record, error_record
from django.db.transaction import atomic
logger = logging.getLogger('docbow.mail_interface')
@ -67,7 +67,7 @@ In case of failure the following return value is returned:
mail = email.message_from_binary_file(open(options['file'], 'rb'))
else:
mail = email.message_from_binary_file(sys.stdin.buffer)
except email.errors.MessageParseError as e:
except email.errors.MessageParseError:
self.error('5.6.0 Error parsing message', exit_code=1)
if settings.SENDMAIL_DEBUG_MBOX:
try:
@ -77,7 +77,7 @@ In case of failure the following return value is returned:
logger.exception('mbox exception')
try:
self.handle_mail(mail, (options['recipient'],), **options)
except Exception as e:
except Exception:
logger.exception('Unknown exception')
self.error('5.6.0 Internal error when handling the mail', exit_code=5)
@ -105,7 +105,7 @@ In case of failure the following return value is returned:
if m:
result = []
for content, encoding in email.header.decode_header(filename):
result.append(force_text(content, encoding or 'ascii'))
result.append(force_str(content, encoding or 'ascii'))
return ''.join(result)
else:
return filename
@ -126,7 +126,7 @@ In case of failure the following return value is returned:
attachments = []
recipients = []
mailing_list_recipients = []
description = u''
description = ''
from_email = email.utils.parseaddr(options['sender'])[1]
if options.get('sender'):
try:
@ -171,7 +171,7 @@ In case of failure the following return value is returned:
else:
try:
subject = u2u_decode(subject)
except Exception as e:
except Exception:
content_errors.append('The subject cannot be decoded')
else:
try:
@ -187,7 +187,7 @@ In case of failure the following return value is returned:
charset = part.get_content_charset('us-ascii')
for cset in (charset, 'iso-8859-15', 'utf-8'):
try:
description = force_text(part.get_payload(decode=True), cset)
description = force_str(part.get_payload(decode=True), cset)
except UnicodeDecodeError:
continue
break

View File

@ -1,6 +1,6 @@
from django.contrib.auth.models import User
from django.db.models.signals import pre_save, pre_delete
from django.conf import settings
from django.contrib.auth.models import User
from django.db.models.signals import pre_delete, pre_save
from django.dispatch import receiver
try:
@ -16,7 +16,7 @@ except:
'''Delete instances on authentic side'''
if using != 'default':
return
if not 'authentic' in settings.DATABASES:
if 'authentic' not in settings.DATABASES:
return
username = instance.username
A2User.objects.using('authentic').filter(username=username).delete()
@ -26,7 +26,7 @@ except:
'''Create new instance on authentic side'''
if using != 'default':
return
if not 'authentic' in settings.DATABASES:
if 'authentic' not in settings.DATABASES:
return
if instance.id:
old_instance = User.objects.using(using).get(id=instance.id)

View File

@ -1,9 +1,9 @@
from django.conf import settings
from django.conf.urls import url, include
from django.urls import include, path
if 'mellon' in settings.INSTALLED_APPS:
urlpatterns = [
url(r'accounts/mellon/', include('mellon.urls')),
path('accounts/mellon/', include('mellon.urls')),
]
else:
urlpatterns = []

View File

@ -1,8 +1,5 @@
# -*- coding: utf-8 -*-
import os
import logging.handlers
from django.core.exceptions import ImproperlyConfigured
import os
gettext_noop = lambda s: s
@ -29,12 +26,12 @@ 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",
'Administrateurs des groupes',
'Administrateurs des types de document',
'Administrateurs des utilisateurs',
"Utilisateurs de l'application",
)
CONTACT_GROUPS = (u'Contact « Administrateur du système »',)
CONTACT_GROUPS = ('Contact « Administrateur du système »',)
LOCALE_PATHS = (os.path.join(BASE_DIR, 'locale'),)
DEFAULT_FROM_EMAIL = 'admin@example.com'
CONTACT_SUBJECT_PREFIX = 'Contact depuis docbow: '
@ -54,14 +51,14 @@ OVH_SMS_PASSWORD = ''
OVH_SMS_FROM = 'Dauvergne'
DOCBOW_SMS_CARRIER_CLASS = 'docbow_project.docbow.sms_carrier_ovh.OVHSMSCarrier'
DOCBOW_ORGANIZATION_SHORT = 'PFWB'
DOCBOW_ORGANIZATION = u'Parlement de la Fédération Wallonie-Bruxelles'
DOCBOW_ORGANIZATION = 'Parlement de la Fédération Wallonie-Bruxelles'
DOCBOW_NOTIFIERS = (
'docbow_project.docbow.notification.MailNotifier',
'docbow_project.docbow.notification.SMSNotifier',
)
DOCBOW_PFWB_GED_DIRECTORY = '/var/lib/docbow/ged/'
DOCBOW_PFWB_SENDMAIL_DEFAULT_TYPE_ID = None
DOCBOW_PFWB_SENDMAIL_DEFAULT_TYPE_NAME = u'Divers'
DOCBOW_PFWB_SENDMAIL_DEFAULT_TYPE_NAME = 'Divers'
DOCBOW_PFWB_SENDMAIL_TABELLIO_EXPEDITION_EMAIL = 'commande.documents@pfwb.be'
DOCBOW_PFWB_SENDMAIL_TABELLIO_EXPEDITION_USER_ID = None
DOCBOW_PFWB_SENDMAIL_ATTACHED_FILE_EMAIL = 'dontknow@pfwb.be'
@ -84,7 +81,7 @@ MANAGERS = ADMINS
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'docbow',
}
}

View File

@ -1,10 +1,8 @@
from django.conf.urls import include, url
from django.conf import settings
from django.contrib import admin
import django.contrib.staticfiles.views
import django.views.defaults
from django.conf import settings
from django.contrib import admin
from django.urls import include, path, re_path
import docbow_project.docbow.views
@ -13,14 +11,14 @@ admin.autodiscover()
from .docbow.admin import site as docbow_admin_site
urlpatterns = [
url(r'^', include('docbow_project.docbow.urls')),
url(r'^robots.txt', docbow_project.docbow.views.robots),
url(r'^accounts/', include('docbow_project.docbow.auth_urls')),
url(r'^superadmin/', admin.site.urls, name='admin'),
url(r'^admin/', docbow_admin_site.urls, name='docbow_admin'),
path('', include('docbow_project.docbow.urls')),
re_path(r'^robots.txt', docbow_project.docbow.views.robots),
path('accounts/', include('docbow_project.docbow.auth_urls')),
re_path(r'^superadmin/', admin.site.urls, name='admin'),
re_path(r'^admin/', docbow_admin_site.urls, name='docbow_admin'),
]
if settings.DEBUG:
urlpatterns += [
url(r'^static/(?P<path>.*)$', django.contrib.staticfiles.views.serve),
re_path(r'^static/(?P<path>.*)$', django.contrib.staticfiles.views.serve),
]

View File

@ -7,7 +7,6 @@ import os
import sys
import xml.etree.ElementTree as ET
"""Merge multiple JUnit XML files into a single results file.
Output dumps to sdtdout.
example usage:

View File

@ -1,14 +1,14 @@
#!env python
import subprocess
import os
import subprocess
import sys
from setuptools import setup, find_packages
from setuptools.command.install_lib import install_lib as _install_lib
from distutils.command.build import build as _build
from setuptools.command.sdist import sdist
from distutils.cmd import Command
from distutils.command.build import build as _build
from setuptools import find_packages, setup
from setuptools.command.install_lib import install_lib as _install_lib
from setuptools.command.sdist import sdist
class eo_sdist(sdist):
@ -29,7 +29,7 @@ def get_version():
tag exists, take 0.0- and add the length of the commit log.
"""
if os.path.exists('VERSION'):
with open('VERSION', 'r') as v:
with open('VERSION') as v:
return v.read()
if os.path.exists('.git'):
p = subprocess.Popen(

View File

@ -1,12 +1,11 @@
import os
import sys
from django.contrib.auth.models import User
import pytest
from django.contrib.auth.models import User
from docbow_project.docbow.models import DocbowProfile, FileType
sys.path.append(os.path.join(os.path.dirname(__file__), 'helpers'))

View File

@ -4,7 +4,6 @@ from webtest import Upload
from docbow_project.docbow.models import FileType
MEDIA_ROOT = tempfile.mkdtemp()

View File

@ -1,13 +1,12 @@
from datetime import datetime, timedelta
from datetime import timedelta
from django.contrib.auth.models import User
from django.core import management
from django.utils.timezone import localtime, now
from docbow_project.docbow.models import Document, DeletedDocument
from utils import assert_can_see_doc, send_file
from docbow_project.docbow.models import DeletedDocument, Document
def test_forward_docs(app, users, settings, filetypes):
sender = User.objects.get(username='user-1')

View File

@ -7,41 +7,39 @@ Replace this with more appropriate tests for your application.
import re
import tempfile
from unittest import mock
from django.test import TestCase
from django.test.utils import override_settings
import pytest
from django.contrib.auth.models import User
from django.contrib.auth.tokens import default_token_generator
from django.core import mail, management
from django.core.files.base import ContentFile
from django.test import Client
from django.utils.encoding import force_bytes, force_text
from django.test import Client, TestCase
from django.test.utils import override_settings
from django.utils.encoding import force_bytes, force_str
from django.utils.http import urlsafe_base64_encode
import mock
import pytest
from docbow_project.docbow import app_settings, notification
from docbow_project.docbow.models import (
Document,
AttachedFile,
Mailbox,
Notification,
AutomaticForwarding,
Delegation,
DocbowProfile,
MailingList,
generate_filename,
Document,
FileType,
FileTypeAttachedFileKind,
Delegation,
all_emails,
is_guest,
Mailbox,
MailingList,
Notification,
NotificationPreference,
AutomaticForwarding,
all_emails,
generate_filename,
is_guest,
)
from docbow_project.docbow.notification import MailNotifier
from docbow_project.docbow.upload_views import file_response
from docbow_project.docbow.utils import file_match_mime_types
MEDIA_ROOT = tempfile.mkdtemp()
@ -187,7 +185,7 @@ class BasicTestCase(BaseTestCase):
management.call_command('notify')
assert len(mail.outbox) == 20
outbox = sorted(mail.outbox, key=lambda m: tuple(sorted(m.to)))
MAIL_LINK_RE = re.compile('https?://[^/]+/inbox/\d+/')
MAIL_LINK_RE = re.compile(r'https?://[^/]+/inbox/\d+/')
for message, i in zip(outbox, range(20)):
recipient = self.users[i // 2]
if app_settings.PERSONAL_EMAIL:
@ -201,7 +199,7 @@ class BasicTestCase(BaseTestCase):
class UtilsTestCase(BaseTestCase):
def setUp(self):
super(UtilsTestCase, self).setUp()
super().setUp()
self.user1, self.user2 = self.users[:2]
self.user2.docbowprofile.is_guest = True
self.user2.docbowprofile.save()
@ -210,7 +208,7 @@ class UtilsTestCase(BaseTestCase):
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))
assert set(all_emails(self.user1)) == {self.user1.email, self.user1.docbowprofile.personal_email}
def test_document_manager(self):
with self.assertNumQueries(1):
@ -221,16 +219,16 @@ class UtilsTestCase(BaseTestCase):
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']))
filenames = {filename.strip() for filename in document.filenames().split(',')}
self.assertEqual(filenames, {'file0.pdf', 'file1.pdf'})
self.assertEqual(set(document.user_human_to()), {'user-0', 'user-1'})
self.assertEqual(document.group_human_to(), [])
self.assertEqual(set(document.human_to()), set(['user-0', 'user-1']))
self.assertEqual(set(document.human_to()), {'user-0', 'user-1'})
self.assertIsNotNone(document.filename_links())
assert set(document.to()) == set((self.user1, self.user2))
assert set(document.to()) == {self.user1, self.user2}
assert dict(document.to_with_origin()) == {
self.user1: set(['--direct--']),
self.user2: set(['--direct--']),
self.user1: {'--direct--'},
self.user2: {'--direct--'},
}
self.assertEqual(
sorted(map(lambda x: x.pk, document.delivered_to())), sorted([self.user1.pk, self.user2.pk])
@ -285,12 +283,12 @@ class DelegatesTestCase(BaseTestCase):
c.login(username='user-0', password='password')
response = c.get('/outbox/')
self.assertIn('/outbox/%s/' % document.pk, force_text(response.content))
self.assertIn('/outbox/%s/' % document.pk, force_str(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))
self.assertNotIn('/inbox/%s/' % document.pk, force_str(response.content))
response = c.get('/inbox/%s/' % document.pk)
self.assertEqual(response.status_code, 302)
@ -299,26 +297,26 @@ class DelegatesTestCase(BaseTestCase):
c.login(username='user-1', password='password')
response = c.get('/inbox/')
self.assertIn('/inbox/%s/' % document.pk, force_text(response.content))
self.assertIn('/inbox/%s/' % document.pk, force_str(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))
self.assertNotIn('/outbox/%s/' % document.pk, force_str(response.content))
# 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))
self.assertNotIn('/inbox/%s/' % document.pk, force_str(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))
self.assertNotIn('/outbox/%s/' % document.pk, force_str(response.content))
response = c.get('/outbox/%s/' % document.pk)
self.assertEqual(response.status_code, 302)
@ -375,7 +373,6 @@ class NotificationToDelegatesTestCase(TestCase):
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)
document.to_user.set(user_recipients)
@ -403,9 +400,7 @@ 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({notif.user for notif in DummyNotifier.notifications}, {recipient, delegate})
delegate.is_active = False
delegate.save()
@ -463,8 +458,7 @@ def test_signals(users_fixture, settings, monkeypatch, tmpdir):
settings.MEDIA_ROOT = tmpdir.strpath
class MockMiddleware(object):
class MockMiddleware:
NO_USER = '-'
def get_extra(self):
@ -540,9 +534,8 @@ def test_password_reset(users_fixture, settings, monkeypatch, client):
@pytest.mark.django_db
def test_password_reset_confirm_get(users_fixture, client):
user = users_fixture[0]
uid = force_text(urlsafe_base64_encode(force_bytes(user.id)))
uid = force_str(urlsafe_base64_encode(force_bytes(user.id)))
token = default_token_generator.make_token(user)
response = client.get('/accounts/password/reset/confirm/%s/%s/' % (uid, token))
@ -550,14 +543,13 @@ def test_password_reset_confirm_get(users_fixture, client):
redirect_url = '/accounts/password/reset/confirm/%s/set-password/' % uid
assert response['Location'].endswith(redirect_url)
response = client.get(redirect_url)
assert 'new_password' in force_text(response.content)
assert 'new_password' in force_str(response.content)
@pytest.mark.django_db
def test_password_reset_confirm_post(users_fixture, client):
user = users_fixture[0]
uid = force_text(urlsafe_base64_encode(force_bytes(user.id)))
uid = force_str(urlsafe_base64_encode(force_bytes(user.id)))
token = default_token_generator.make_token(user)
response = client.get('/accounts/password/reset/confirm/%s/%s/' % (uid, token))
assert response.status_code == 302

View File

@ -2,10 +2,10 @@ import tempfile
import uuid
import zipfile
import pytest
from django.contrib.auth.models import Group, User
from django.utils import translation
import pytest
from utils import assert_can_see_doc, assert_cannot_see_doc, send_file
from webtest import Upload
from docbow_project.docbow.models import (
@ -13,10 +13,9 @@ from docbow_project.docbow.models import (
DeletedDocument,
Document,
FileType,
MailingList,
FileTypeAttachedFileKind,
MailingList,
)
from utils import assert_can_see_doc, assert_cannot_see_doc, send_file
MEDIA_ROOT = tempfile.mkdtemp()
@ -101,7 +100,7 @@ def test_sendfile_selector(app, filetypes, users):
resp = app.get('/send_file/')
for ft in FileType.objects.all():
assert ft.name in resp.text
assert u'<a href="/send_file/%s/?">' % ft.pk in resp.text
assert '<a href="/send_file/%s/?">' % ft.pk in resp.text
def test_sendfile(app, filetypes, users, settings):

View File

@ -5,16 +5,14 @@ when you run "manage.py test".
Replace this with more appropriate tests for your application.
"""
from io import StringIO
import tempfile
import sys
import tempfile
from contextlib import contextmanager
from functools import wraps
from io import StringIO
from unittest import mock
from django.utils.encoding import force_bytes, force_text
import mock
from django.utils.encoding import force_bytes, force_str
MEDIA_ROOT = tempfile.mkdtemp()
@ -30,7 +28,7 @@ def captured_output():
sys.stdout, sys.stderr = old_out, old_err
class stderr_output(object):
class stderr_output:
def __init__(self, output):
self.output = output
@ -45,7 +43,7 @@ class stderr_output(object):
return f
class stdout_output(object):
class stdout_output:
def __init__(self, output):
self.output = output
@ -60,22 +58,21 @@ class stdout_output(object):
return f
from django.contrib.auth.models import User
from django.core import management
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 django_journal.models import Journal
from docbow_project.docbow.models import AttachedFile, Document, FileType, MailingList
from docbow_project.pfwb.models import PloneFileType, TabellioDocType
EXPEDITION_EMAIL = 'expedition@example.com'
RECIPIENT_EMAIL = 'recipient@example.com'
RECIPIENT_LIST_EMAIL = 'liste-ma-liste@example.com'
class MockUrlib(object):
class MockUrlib:
def urlopen(self, url):
return self
@ -263,15 +260,15 @@ class SendMailAttachedFileTestCase(TestCase):
self.to_list.members.add(self.to_user)
def build_message(self, filetype, to_addr, from_addr, content, attached_files):
import random
from email import encoders
from email.header import Header
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import random
message = MIMEMultipart()
message['Subject'] = Header(force_text(filetype), 'utf-8')
message['Subject'] = Header(force_str(filetype), 'utf-8')
message['To'] = Header(to_addr, 'utf-8')
message['From'] = Header(from_addr, 'utf-8')
message['Message-ID'] = '<%s@example.com>' % random.random()
@ -321,10 +318,11 @@ class PushDocumentTestCase(TestCase):
shutil.rmtree(self.ged_dir)
def test_push_document1(self):
from django.core.files.base import ContentFile
import os.path
from glob import glob
from django.core.files.base import ContentFile
with self.settings(DOCBOW_PFWB_GED_DIRECTORY=self.ged_dir):
FROM_USERNAME = 'from_user'
FROM_FIRST_NAME = 'from_first_name'
@ -344,8 +342,8 @@ class PushDocumentTestCase(TestCase):
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)
pattern1 = f'{self.document.id}-*-{self.attached_file.name}.json'
pattern2 = f'{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
@ -359,9 +357,9 @@ class PushDocumentTestCase(TestCase):
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['title'] == force_str(self.filetype)
assert json_content['description'] == DESCRIPTION
assert json_content['sender'] == u'{0} {1} ({2})'.format(
assert json_content['sender'] == '{} {} ({})'.format(
FROM_FIRST_NAME, FROM_LAST_NAME, FROM_USERNAME
)
@ -399,9 +397,9 @@ class ArchiveTestCase(TestCase):
shutil.rmtree(self.archive_dir)
def test_archive(self):
import os.path
import glob
import datetime
import glob
import os.path
with captured_output() as (out, err):
management.call_command('archive2', self.archive_dir, 0)

View File

@ -1,12 +1,12 @@
from datetime import datetime
import pytest
from django.conf import settings
from django.contrib.auth.models import User
from django.core import management
import pytest
from sqlalchemy import create_engine
from sqlalchemy.sql import func
from sqlalchemy_utils import database_exists, create_database, drop_database
from sqlalchemy_utils import create_database, database_exists, drop_database
from docbow_project.docbow.models import DocbowProfile, FileType, MailingList
from docbow_project.pfwb.models import TabellioDocType
@ -18,8 +18,8 @@ from docbow_project.pfwb.tabellio import (
TComppol,
TPer,
TPershistoline,
TTypehistoper,
TTypedoc,
TTypehistoper,
)

View File

@ -8,7 +8,7 @@ MELLON_ADAPTER = ('docbow_project.pfwb.mellon_adapter.PFWBMellonAdapter',)
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'ENGINE': 'django.db.backends.postgresql',
'TEST': {
'NAME': 'docbow-test-%s' % os.environ.get('BRANCH_NAME', '').replace('/', '-')[:63],
},

View File

@ -1,11 +1,10 @@
from django.contrib import auth
import pytest
import lasso
import pytest
from django.contrib import auth
from docbow_project.docbow.models import DocbowProfile
from docbow_project.pfwb.mellon_adapter import PFWBMellonAdapter
User = auth.get_user_model()

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
"""
This file demonstrates writing tests using the unittest module. These will pass
when you run "manage.py test".
@ -6,13 +5,13 @@ when you run "manage.py test".
Replace this with more appropriate tests for your application.
"""
from io import StringIO
import tempfile
import sys
import tempfile
from contextlib import contextmanager
from functools import wraps
from io import StringIO
from django.utils.encoding import force_bytes, force_text
from django.utils.encoding import force_bytes, force_str
MEDIA_ROOT = tempfile.mkdtemp()
@ -28,7 +27,7 @@ def captured_output():
sys.stdout, sys.stderr = old_out, old_err
class stderr_output(object):
class stderr_output:
def __init__(self, output):
self.output = output
@ -43,7 +42,7 @@ class stderr_output(object):
return f
class stdout_output(object):
class stdout_output:
def __init__(self, output):
self.output = output
@ -58,19 +57,19 @@ class stdout_output(object):
return f
from django.contrib.auth.models import User
from django.core import management
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 Document, FileType, MailingList
EXPEDITION_EMAIL = 'expedition@example.com'
RECIPIENT_EMAIL = 'recipient@example.com'
PRIVATE_RECIPIENT_EMAIL = 'recipient-private@example.com'
class MessageFile(object):
class MessageFile:
def __init__(self, filetype, to_addr, from_addr, content, attached_files, headers={}):
self.filetype = filetype
self.to_addr = to_addr
@ -81,15 +80,15 @@ class MessageFile(object):
self.message_file = tempfile.NamedTemporaryFile()
def __enter__(self):
import random
from email import encoders
from email.header import Header
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import random
message = MIMEMultipart()
message['Subject'] = Header(force_text(self.filetype), 'utf-8')
message['Subject'] = Header(force_str(self.filetype), 'utf-8')
message['To'] = Header(self.to_addr, 'utf-8')
message['From'] = Header(self.from_addr, 'utf-8')
message['Message-ID'] = '<%s@example.com>' % random.random()

View File

@ -6,7 +6,7 @@ DOCBOW_PRIVATE_DOCUMENTS = True
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'ENGINE': 'django.db.backends.postgresql',
'TEST': {
'NAME': 'docbow-test-%s' % os.environ.get('BRANCH_NAME', '').replace('/', '-')[:63],
},

View File

@ -6,7 +6,7 @@ INSTALLED_APPS += ('mellon',)
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'ENGINE': 'django.db.backends.postgresql',
'TEST': {
'NAME': 'docbow-test-%s' % os.environ.get('BRANCH_NAME', '').replace('/', '-')[:63],
},

View File

@ -1,5 +1,5 @@
from django.contrib.auth.models import User
import pytest
from django.contrib.auth.models import User
from docbow_project.docbow.auth_backend import DocbowMellonAuthBackend
from docbow_project.docbow.models import Delegation, DocbowProfile

View File

@ -1,8 +1,9 @@
from django.contrib.auth.models import User
from unittest import mock
import mellon.models
import mock
import pytest
import requests
from django.contrib.auth.models import User
from docbow_project.docbow.models import Delegation, DocbowProfile
@ -29,7 +30,7 @@ def user():
return user
class MockResp(object):
class MockResp:
def __init__(self, json=None, excp=None):
self._json = json
self._excp = excp
@ -45,9 +46,10 @@ class MockResp(object):
@pytest.mark.django_db
def test_create_delegate_sso(a2settings, app, monkeypatch, users):
a2settings.AUTHENTIC_ROLE = 'roleuuid'
import docbow_project.docbow.utils
import mellon
import docbow_project.docbow.utils
mellon.models.Issuer.objects.create(entity_id=a2settings.AUTHENTIC_URL + 'idp/saml2/metadata')
mock_resp1 = MockResp(json={'uuid': '1234'})