Commit 74609fc4 authored by Samuel GAIST's avatar Samuel GAIST Committed by Flavio TARSETTI

[common][all] Pre-commit cleanup

parent ccc22d53
Pipeline #42574 passed with stage
in 15 minutes and 58 seconds
......@@ -25,19 +25,22 @@
# #
###############################################################################
from django.contrib import admin, messages
from django.contrib.admin import helpers
import logging
from functools import partial
from django.conf import settings
from django.shortcuts import render
from django.contrib import admin
from django.contrib import messages
from django.contrib.admin import helpers
from django.core.mail import EmailMessage
from django.shortcuts import render
from django.template.loader import render_to_string
from guardian import admin as guardian_admin
from functools import partial
from .. import __version__
from ..common.models import Shareable
from .. import __version__
logger = logging.getLogger(__name__)
class GuardedModelAdminMixin(guardian_admin.GuardedModelAdminMixin):
......@@ -55,14 +58,14 @@ class Django18ProofGuardedModelAdmin(GuardedModelAdminMixin, admin.ModelAdmin):
def notify_by_email(attribute=None):
'''Generates a notify_by_email() admin action. If attribute is set, then,
"""Generates a notify_by_email() admin action. If attribute is set, then,
use it as to restrict the number of users the email will be sent to.
'''
"""
def notify_by_email_inner(modeladmin, request, queryset):
'''Notifies users by e-mail on admin request'''
"""Notifies users by e-mail on admin request"""
if 'send' in request.POST:
if "send" in request.POST:
# sends the message after user confirmation
for instance in queryset:
......@@ -70,42 +73,49 @@ def notify_by_email(attribute=None):
users = instance.users_with_access()
if not users:
modeladmin.message_user(request, "No users to e-mail for " \
"'%s'" % instance.fullname(), level=messages.WARNING)
return
modeladmin.message_user(
request,
"No users to e-mail for " "'%s'" % instance.fullname(),
level=messages.WARNING,
)
return
# filter users using notification preferences
users = [u for u in users if getattr(u.accountsettings, \
attribute)]
users = [u for u in users if getattr(u.accountsettings, attribute)]
if not users:
modeladmin.message_user(request,
"Affected users for '%s' don't want to be e-mailed" % \
instance.fullname(), level=messages.WARNING)
return
modeladmin.message_user(
request,
"Affected users for '%s' don't want to be e-mailed"
% instance.fullname(),
level=messages.WARNING,
)
return
if instance.sharing == Shareable.PUBLIC:
action = 'made public'
action = "made public"
elif instance.sharing == Shareable.SHARED:
action = 'shared with you (or a team you are in)'
action = "shared with you (or a team you are in)"
else:
modeladmin.message_user(request,
"'%s' is private. Not e-mailing anyone." % \
instance.fullname(), level=messages.ERROR)
modeladmin.message_user(
request,
"'%s' is private. Not e-mailing anyone." % instance.fullname(),
level=messages.ERROR,
)
return
objurl = request.build_absolute_uri(instance.get_absolute_url())
ctx = {
'object': instance,
'verbose_name': instance._meta.verbose_name,
'objurl': objurl,
'beat_version': __version__,
'action': action,
"object": instance,
"verbose_name": instance._meta.verbose_name,
"objurl": objurl,
"beat_version": __version__,
"action": action,
}
emails = [u.email for u in users]
subj = render_to_string('common/sharing_email_subject.txt', ctx)
body = render_to_string('common/sharing_email_body.txt', ctx)
subj = render_to_string("common/sharing_email_subject.txt", ctx)
body = render_to_string("common/sharing_email_body.txt", ctx)
mesg = EmailMessage(
subj.strip(),
......@@ -115,20 +125,27 @@ def notify_by_email(attribute=None):
bcc=emails,
)
plural = '' if len(emails) == 1 else 's'
plural = "" if len(emails) == 1 else "s"
try:
mesg.send()
except Exception:
errormsg = "Could not send e-mails to %d user%s of '%s'" \
% (len(emails), plural, instance.fullname())
errormsg = "Could not send e-mails to %d user%s of '%s'" % (
len(emails),
plural,
instance.fullname(),
)
modeladmin.message_user(request, errormsg)
import traceback
logger.warn(errormsg + ". Exception caught: %s",
traceback.format_exc())
modeladmin.message_user(request, "Successfully notified %d " \
"user%s of '%s'" % \
(len(emails), plural, instance.fullname()))
logger.warn(
errormsg + ". Exception caught: %s", traceback.format_exc()
)
modeladmin.message_user(
request,
"Successfully notified %d "
"user%s of '%s'" % (len(emails), plural, instance.fullname()),
)
else:
# presents the user with an intermediary page asking to confirm
......@@ -145,16 +162,15 @@ def notify_by_email(attribute=None):
return render(
request,
'common/email_confirmation.html',
"common/email_confirmation.html",
{
'users': users_per_instance,
'title': 'Confirm mass e-mail submission',
'queryset': queryset,
'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME,
"users": users_per_instance,
"title": "Confirm mass e-mail submission",
"queryset": queryset,
"action_checkbox_name": helpers.ACTION_CHECKBOX_NAME,
},
)
notify_by_email_inner.short_description = 'Notify affected users'
notify_by_email_inner.short_description = "Notify affected users"
return notify_by_email_inner
......@@ -26,27 +26,26 @@
###############################################################################
from django.shortcuts import get_object_or_404
from rest_framework import status
from rest_framework import exceptions as drf_exceptions
from rest_framework import generics
from rest_framework import permissions as drf_permissions
from rest_framework import exceptions as drf_exceptions
from rest_framework import status
from rest_framework.response import Response
from rest_framework.reverse import reverse
from .models import Contribution, Versionable
from .exceptions import ShareError, BaseCreationError
from .serializers import (
SharingSerializer,
ContributionSerializer,
CheckNameSerializer,
DiffSerializer,
)
from .mixins import CommonContextMixin, SerializerFieldsMixin
from .utils import py3_cmp
from . import permissions as beat_permissions
from . import is_true
from . import permissions as beat_permissions
from .exceptions import BaseCreationError
from .exceptions import ShareError
from .mixins import CommonContextMixin
from .mixins import SerializerFieldsMixin
from .models import Contribution
from .models import Versionable
from .serializers import CheckNameSerializer
from .serializers import ContributionSerializer
from .serializers import DiffSerializer
from .serializers import SharingSerializer
from .utils import py3_cmp
class CheckContributionNameView(CommonContextMixin, generics.CreateAPIView):
......
......@@ -27,7 +27,7 @@
from django.apps import AppConfig
class CommonAppConfig(AppConfig):
class CommonAppConfig(AppConfig):
def ready(self):
from .signals.handlers import on_shared
from .signals.handlers import on_shared # noqa: F401
......@@ -44,14 +44,18 @@ class BeatWebError(Exception):
def errors(self):
return self.__message
class NotUserNorTeam(BeatWebError):
pass
class BaseCreationError(BeatWebError):
pass
class ShareError(BeatWebError):
pass
class ContributionCreationError(BaseCreationError):
pass
......@@ -26,7 +26,6 @@
###############################################################################
import simplejson as json
from rest_framework import serializers
from rest_framework.fields import JSONField as drf_JSONField
......
......@@ -25,22 +25,23 @@
# #
###############################################################################
from actstream.managers import ActionManager
from actstream.managers import stream
from actstream.registry import check
from django.contrib.contenttypes.models import ContentType
from django.db.models import Q
from actstream.managers import ActionManager, stream
from actstream.registry import check
from beat.web.team.models import Team
class BeatActionManager(ActionManager):
class BeatActionManager(ActionManager):
@stream
def public_for_user(self, obj, **kwargs):
"""
Only return public actions for given user
"""
check(obj)
kwargs['public'] = True
kwargs["public"] = True
return self.any(obj, **kwargs)
@stream
......@@ -53,30 +54,18 @@ class BeatActionManager(ActionManager):
"""
check(obj)
ctype = ContentType.objects.get_for_model(obj)
query = Q(
target_content_type=ctype,
target_object_id=obj.pk,
)
query = Q(target_content_type=ctype, target_object_id=obj.pk,)
if obj.teams.count() > 0:
team_ctype = ContentType.objects.get_for_model(Team)
team_ids = [team.id for team in obj.teams.all()]
query |= Q(
target_content_type=team_ctype,
target_object_id__in=team_ids,
)
query |= Q(target_content_type=team_ctype, target_object_id__in=team_ids,)
public_query = ~Q(
actor_content_type=ctype,
actor_object_id=obj.pk,
) & ~Q(
target_content_type=ctype,
target_object_id=obj.pk,
) & ~Q(
action_object_content_type=ctype,
action_object_object_id=obj.pk,
) & Q(
public=True
public_query = (
~Q(actor_content_type=ctype, actor_object_id=obj.pk,)
& ~Q(target_content_type=ctype, target_object_id=obj.pk,)
& ~Q(action_object_content_type=ctype, action_object_object_id=obj.pk,)
& Q(public=True)
)
return self.filter(query | public_query, **kwargs)
......@@ -71,7 +71,7 @@ class SerializerFieldsMixin(object):
exclude_fields = ["sharing"] + exclude_fields
if request.user.is_anonymous:
exclude_fields = ['is_owner'] + exclude_fields
exclude_fields = ["is_owner"] + exclude_fields
fields = [field for field in fields if field not in exclude_fields]
......
......@@ -25,13 +25,17 @@
# #
###############################################################################
from rest_framework.response import Response
from rest_framework import status
from rest_framework.response import Response
class BadRequestResponse(Response):
def __init__(self, data):
super(BadRequestResponse, self).__init__(data, status=status.HTTP_400_BAD_REQUEST)
super(BadRequestResponse, self).__init__(
data, status=status.HTTP_400_BAD_REQUEST
)
class ForbiddenResponse(Response):
def __init__(self, data=''):
def __init__(self, data=""):
super(ForbiddenResponse, self).__init__(data, status=status.HTTP_403_FORBIDDEN)
......@@ -26,27 +26,23 @@
###############################################################################
import copy
import simplejson as json
import difflib
import simplejson as json
from django.conf import settings
from django.contrib.auth.models import User
from rest_framework import serializers
from rest_framework import exceptions as drf_exceptions
from rest_framework import serializers
from ..team.models import Team
from ..common.utils import ensure_html
from ..common import fields as beat_fields
from ..common.utils import annotate_full_name
from ..common.utils import ensure_html
from ..common.utils import validate_restructuredtext
from ..common import fields as beat_fields
from .models import Shareable, Versionable, Contribution
from ..team.models import Team
from . import fields as serializer_fields
from .models import Contribution
from .models import Shareable
from .models import Versionable
# ----------------------------------------------------------
......
......@@ -26,21 +26,21 @@
###############################################################################
import os
from django.core.files.storage import FileSystemStorage
from django.core.files.base import ContentFile
from django.core.files.base import ContentFile
from django.core.files.storage import FileSystemStorage
#----------------------------------------------------------
# ----------------------------------------------------------
class OverwriteStorage(FileSystemStorage):
def __init__(self, *args, **kwargs):
super(OverwriteStorage, self).__init__(*args, **kwargs)
def get_available_name(self, name, max_length=None):
# If the filename already exists, remove it
if self.exists(name): self.delete(name)
if self.exists(name):
self.delete(name)
return name
def delete(self, name):
......@@ -48,7 +48,8 @@ class OverwriteStorage(FileSystemStorage):
super(OverwriteStorage, self).delete(name)
def rmdir_recursive(path):
if not path or not self.exists(path): return
if not path or not self.exists(path):
return
dirs, files = self.listdir(path)
if not (dirs or files):
os.rmdir(self.path(path))
......@@ -57,7 +58,7 @@ class OverwriteStorage(FileSystemStorage):
rmdir_recursive(os.path.dirname(name))
#----------------------------------------------------------
# ----------------------------------------------------------
def get_file_content(instance, attr):
......@@ -73,27 +74,27 @@ def get_file_content(instance, attr):
AttributeError: If the field does not exist
"""
if hasattr(instance, '_file_contents') and attr in instance._file_contents:
return instance._file_contents[attr]['value']
if hasattr(instance, "_file_contents") and attr in instance._file_contents:
return instance._file_contents[attr]["value"]
f = getattr(instance, attr)
if f is None:
return ''
return ""
try:
f.open()
except:
return ''
except Exception:
return ""
try:
return f.read()
finally:
f.close()
return ''
return ""
#----------------------------------------------------------
# ----------------------------------------------------------
def set_file_content(instance, attr, filename, value):
......@@ -101,22 +102,22 @@ def set_file_content(instance, attr, filename, value):
The file will be created/overwritten by the save() method.
"""
if not(hasattr(instance, '_file_contents')):
if not (hasattr(instance, "_file_contents")):
instance._file_contents = {}
instance._file_contents[attr] = {
'filename': filename,
'value': value,
"filename": filename,
"value": value,
}
#----------------------------------------------------------
# ----------------------------------------------------------
def save_files(instance):
"""Save the changed files (if necessary)"""
if not(hasattr(instance, '_file_contents')):
if not (hasattr(instance, "_file_contents")):
return
for attr in instance._file_contents.keys():
......@@ -124,14 +125,14 @@ def save_files(instance):
if current:
current.delete(save=False)
newfile = ContentFile(instance._file_contents[attr]['value'])
newfile.name = instance._file_contents[attr]['filename']
newfile = ContentFile(instance._file_contents[attr]["value"])
newfile.name = instance._file_contents[attr]["filename"]
setattr(instance, attr, newfile)
del instance._file_contents
#----------------------------------------------------------
# ----------------------------------------------------------
def rename_file(instance, attr, name):
......
......@@ -28,8 +28,8 @@
import os
import shutil
from django.test import TestCase
from django.conf import settings
from django.test import TestCase
try:
from urlparse import urlparse
......@@ -51,72 +51,78 @@ class BaseTestCase(TestCase):
class Meta:
model = None
def checkObjectDBSharingPreferences(self, contribution, reference):
if 'status' not in reference:
reference['status'] = 'private'
if "status" not in reference:
reference["status"] = "private"
if 'shared_with' not in reference:
reference['shared_with'] = []
if "shared_with" not in reference:
reference["shared_with"] = []
if 'shared_with_team' not in reference:
reference['shared_with_team'] = []
if "shared_with_team" not in reference:
reference["shared_with_team"] = []
if 'usable_by' not in reference:
reference['usable_by'] = []
if "usable_by" not in reference:
reference["usable_by"] = []
if 'usable_by_team' not in reference:
reference['usable_by_team'] = []
if "usable_by_team" not in reference:
reference["usable_by_team"] = []
if reference['status'] == 'public':
if reference["status"] == "public":
self.assertEqual(contribution.sharing, Shareable.PUBLIC)
elif reference['status'] == 'usable':
elif reference["status"] == "usable":
self.assertEqual(contribution.sharing, Shareable.USABLE)
elif reference['status'] == 'shared':
elif reference["status"] == "shared":
self.assertEqual(contribution.sharing, Shareable.SHARED)
else:
self.assertEqual(contribution.sharing, Shareable.PRIVATE)
self.assertEqual(contribution.shared_with.count(), len(reference['shared_with']))
self.assertEqual(contribution.shared_with_team.count(), len(reference['shared_with_team']))
self.assertEqual(
contribution.shared_with.count(), len(reference["shared_with"])
)
self.assertEqual(
contribution.shared_with_team.count(), len(reference["shared_with_team"])
)
for user in contribution.shared_with.iterator():
self.assertTrue(user.username in reference['shared_with'])
self.assertTrue(user.username in reference["shared_with"])
for team in contribution.shared_with_team.iterator():
self.assertTrue(team.fullname() in reference['shared_with_team'])
self.assertTrue(team.fullname() in reference["shared_with_team"])
if hasattr(contribution, 'usable_by'):
self.assertEqual(contribution.usable_by.count(), len(reference['usable_by']))
if hasattr(contribution, "usable_by"):
self.assertEqual(
contribution.usable_by.count(), len(reference["usable_by"])
)
for user in contribution.usable_by.iterator():
self.assertTrue(user.username in reference['usable_by'])
self.assertTrue(user.username in reference["usable_by"])
if hasattr(contribution, 'usable_by_team'):
self.assertEqual(contribution.usable_by_team.count(), len(reference['usable_by_team']))
if hasattr(contribution, "usable_by_team"):
self.assertEqual(
contribution.usable_by_team.count(), len(reference["usable_by_team"])
)
for team in contribution.usable_by_team.iterator():
self.assertTrue(team.fullname() in reference['usable_by_team'])
self.assertTrue(team.fullname() in reference["usable_by_team"])
def checkDBSharingPreferences(self, username, object_name, reference):
db_object = self.Meta.model.objects.get(author__username=username, name=object_name, version=1)
db_object = self.Meta.model.objects.get(
author__username=username, name=object_name, version=1
)
self.checkObjectDBSharingPreferences(db_object, reference)
def checkResponse(self, response, status_code, location=None, content_type=None):
self.assertEqual(response.status_code, status_code)
if location is not None:
parsed_location = urlparse(response.get('Location', ''))
self.assertTrue(response.has_header('Location'))
parsed_location = urlparse(response.get("Location", ""))
self.assertTrue(response.has_header("Location"))
self.assertEqual(parsed_location.path, location)
if content_type is not None:
self.assertTrue(response.has_header('Content-Type'))
self.assertEqual(response.get('Content-Type', ''), content_type)
self.assertTrue(response.has_header("Content-Type"))
self.assertEqual(response.get("Content-Type", ""), content_type)
self.assertNotEqual(len(response.content), 0)
if content_type == 'application/json':
if content_type == "application/json":
return response.json()
else:
return response.content
......@@ -131,4 +137,4 @@ def get_algorithms_from_data(data, author_name):
Retrieves the algorithms from author_name in data
"""
return [x for x in data if x['name'] == author_name]
return [x for x in data if x["name"] == author_name]
......@@ -28,17 +28,22 @@
code_suffix = '<br/><i class="fa fa-thumbs-up"></i> The ruler at 80 columns indicate suggested <a href="https://en.wikipedia.org/wiki/POSIX">POSIX line breaks</a> (for readability).<br/><i class="fa fa-thumbs-up"></i> The editor will automatically enlarge to accomodate the entirety of your input<br/><i class="fa fa-thumbs-up"></i> Use <a href="http://codemirror.net/doc/manual.html#commands">keyboard shortcuts</a> for search/replace and faster editing. For example, use Ctrl-F (PC) or Cmd-F (Mac) to search through this box'
Messages = {
'description': 'Describe the object thoroughly using <a href="http://docutils.sourceforge.net/rst.html">reStructuredText mark-up</a>' + code_suffix,
'code': 'The code for this algorithm in <a href="https://www.python.org">Python</a>' + code_suffix,
'uses': 'You can use functions and classes implemented in libraries.<br/>Once added, the library will be automatically imported with the name specified.',
'library_code': 'The code for this library in <a href="https://www.python.org">Python</a>' + code_suffix,
'format': 'The <a href="http://json.org">JSON</a> descriptor for this data format' + code_suffix,
'json': 'The <a href="http://json.org">JSON</a> descriptor for this object' + code_suffix,
'short_description': 'Describe the object succinctly (try to keep it under 80 characters)',
'hash': 'Hashed value of the object contents (<a href="https://docs.python.org/2/library/hashlib.html">SHA256, hexadecimal digest</a>). This field is auto-generated and managed by the platform.',
'algo_name': 'The name for this algorithm (space-like characters will be automatically replaced by dashes)',
'format_name': 'The name for this dataformat (space-like characters will be automatically replaced by dashes)',
'name': 'The name for this object (space-like characters will be automatically replaced by dashes)',
'version': 'The version of this object (an integer starting from 1)',
'shared_library': 'The compiled shared library file implementing your algorithm',
"description": 'Describe the object thoroughly using <a href="http://docutils.sourceforge.net/rst.html">reStructuredText mark-up</a>'
+ code_suffix,
"code": 'The code for this algorithm in <a href="https://www.python.org">Python</a>'
+ code_suffix,
"uses": "You can use functions and classes implemented in libraries.<br/>Once added, the library will be automatically imported with the name specified.",
"library_code": 'The code for this library in <a href="https://www.python.org">Python</a>'
+ code_suffix,
"format": 'The <a href="http://json.org">JSON</a> descriptor for this data format'
+ code_suffix,
"json": 'The <a href="http://json.org">JSON</a> descriptor for this object'
+ code_suffix,
"short_description": "Describe the object succinctly (try to keep it under 80 characters)",
"hash": 'Hashed value of the object contents (<a href="https://docs.python.org/2/library/hashlib.html">SHA256, hexadecimal digest</a>). This field is auto-generated and managed by the platform.',
"algo_name": "The name for this algorithm (space-like characters will be automatically replaced by dashes)",
"format_name": "The name for this dataformat (space-like characters will be automatically replaced by dashes)",
"name": "The name for this object (space-like characters will be automatically replaced by dashes)",
"version": "The version of this object (an integer starting from 1)",
"shared_library": "The compiled shared library file implementing your algorithm",
}
......@@ -29,13 +29,13 @@
Reusable help functions
"""
from django.core.exceptions import ValidationError
from django.utils.encoding import force_text
from django.db.models import CharField, Value as V
from django.db.models import CharField
from django.db.models import Value as V
from django.db.models.functions import Concat
from django.utils.encoding import force_text
from docutils import utils
from docutils.nodes import Element
from docutils.core import Publisher
from docutils.nodes import Element
from ..ui.templatetags.markup import restructuredtext
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment