Blacked the code

This commit is contained in:
Eliot Berriot 2018-06-09 15:36:16 +02:00
commit 62ca3bd736
No known key found for this signature in database
GPG key ID: DD6965E2476E5C27
279 changed files with 8890 additions and 9556 deletions

View file

@ -16,20 +16,19 @@ class TokenHeaderAuth(BaseJSONWebTokenAuthentication):
def get_jwt_value(self, request):
try:
qs = request.get('query_string', b'').decode('utf-8')
qs = request.get("query_string", b"").decode("utf-8")
parsed = parse_qs(qs)
token = parsed['token'][0]
token = parsed["token"][0]
except KeyError:
raise exceptions.AuthenticationFailed('No token')
raise exceptions.AuthenticationFailed("No token")
if not token:
raise exceptions.AuthenticationFailed('Empty token')
raise exceptions.AuthenticationFailed("Empty token")
return token
class TokenAuthMiddleware:
def __init__(self, inner):
# Store the ASGI application we were passed
self.inner = inner
@ -41,5 +40,5 @@ class TokenAuthMiddleware:
except (User.DoesNotExist, exceptions.AuthenticationFailed):
user = AnonymousUser()
scope['user'] = user
scope["user"] = user
return self.inner(scope)

View file

@ -6,34 +6,34 @@ from rest_framework_jwt import authentication
from rest_framework_jwt.settings import api_settings
class JSONWebTokenAuthenticationQS(
authentication.BaseJSONWebTokenAuthentication):
class JSONWebTokenAuthenticationQS(authentication.BaseJSONWebTokenAuthentication):
www_authenticate_realm = 'api'
www_authenticate_realm = "api"
def get_jwt_value(self, request):
token = request.query_params.get('jwt')
if 'jwt' in request.query_params and not token:
msg = _('Invalid Authorization header. No credentials provided.')
token = request.query_params.get("jwt")
if "jwt" in request.query_params and not token:
msg = _("Invalid Authorization header. No credentials provided.")
raise exceptions.AuthenticationFailed(msg)
return token
def authenticate_header(self, request):
return '{0} realm="{1}"'.format(
api_settings.JWT_AUTH_HEADER_PREFIX, self.www_authenticate_realm)
api_settings.JWT_AUTH_HEADER_PREFIX, self.www_authenticate_realm
)
class BearerTokenHeaderAuth(
authentication.BaseJSONWebTokenAuthentication):
class BearerTokenHeaderAuth(authentication.BaseJSONWebTokenAuthentication):
"""
For backward compatibility purpose, we used Authorization: JWT <token>
but Authorization: Bearer <token> is probably better.
"""
www_authenticate_realm = 'api'
www_authenticate_realm = "api"
def get_jwt_value(self, request):
auth = authentication.get_authorization_header(request).split()
auth_header_prefix = 'bearer'
auth_header_prefix = "bearer"
if not auth:
if api_settings.JWT_AUTH_COOKIE:
@ -44,14 +44,16 @@ class BearerTokenHeaderAuth(
return None
if len(auth) == 1:
msg = _('Invalid Authorization header. No credentials provided.')
msg = _("Invalid Authorization header. No credentials provided.")
raise exceptions.AuthenticationFailed(msg)
elif len(auth) > 2:
msg = _('Invalid Authorization header. Credentials string '
'should not contain spaces.')
msg = _(
"Invalid Authorization header. Credentials string "
"should not contain spaces."
)
raise exceptions.AuthenticationFailed(msg)
return auth[1]
def authenticate_header(self, request):
return '{0} realm="{1}"'.format('Bearer', self.www_authenticate_realm)
return '{0} realm="{1}"'.format("Bearer", self.www_authenticate_realm)

View file

@ -5,7 +5,7 @@ from funkwhale_api.common import channels
class JsonAuthConsumer(JsonWebsocketConsumer):
def connect(self):
try:
assert self.scope['user'].pk is not None
assert self.scope["user"].pk is not None
except (AssertionError, AttributeError, KeyError):
return self.close()

View file

@ -3,18 +3,19 @@ from dynamic_preferences.registries import global_preferences_registry
from funkwhale_api.common import preferences
common = types.Section('common')
common = types.Section("common")
@global_preferences_registry.register
class APIAutenticationRequired(
preferences.DefaultFromSettingMixin, types.BooleanPreference):
preferences.DefaultFromSettingMixin, types.BooleanPreference
):
section = common
name = 'api_authentication_required'
verbose_name = 'API Requires authentication'
setting = 'API_AUTHENTICATION_REQUIRED'
name = "api_authentication_required"
verbose_name = "API Requires authentication"
setting = "API_AUTHENTICATION_REQUIRED"
help_text = (
'If disabled, anonymous users will be able to query the API'
'and access music data (as well as other data exposed in the API '
'without specific permissions).'
"If disabled, anonymous users will be able to query the API"
"and access music data (as well as other data exposed in the API "
"without specific permissions)."
)

View file

@ -6,34 +6,31 @@ from funkwhale_api.music import utils
PRIVACY_LEVEL_CHOICES = [
('me', 'Only me'),
('followers', 'Me and my followers'),
('instance', 'Everyone on my instance, and my followers'),
('everyone', 'Everyone, including people on other instances'),
("me", "Only me"),
("followers", "Me and my followers"),
("instance", "Everyone on my instance, and my followers"),
("everyone", "Everyone, including people on other instances"),
]
def get_privacy_field():
return models.CharField(
max_length=30, choices=PRIVACY_LEVEL_CHOICES, default='instance')
max_length=30, choices=PRIVACY_LEVEL_CHOICES, default="instance"
)
def privacy_level_query(user, lookup_field='privacy_level'):
def privacy_level_query(user, lookup_field="privacy_level"):
if user.is_anonymous:
return models.Q(**{
lookup_field: 'everyone',
})
return models.Q(**{lookup_field: "everyone"})
return models.Q(**{
'{}__in'.format(lookup_field): [
'followers', 'instance', 'everyone'
]
})
return models.Q(
**{"{}__in".format(lookup_field): ["followers", "instance", "everyone"]}
)
class SearchFilter(django_filters.CharFilter):
def __init__(self, *args, **kwargs):
self.search_fields = kwargs.pop('search_fields')
self.search_fields = kwargs.pop("search_fields")
super().__init__(*args, **kwargs)
def filter(self, qs, value):

View file

@ -4,17 +4,20 @@ from funkwhale_api.common import scripts
class Command(BaseCommand):
help = 'Run a specific script from funkwhale_api/common/scripts/'
help = "Run a specific script from funkwhale_api/common/scripts/"
def add_arguments(self, parser):
parser.add_argument('script_name', nargs='?', type=str)
parser.add_argument("script_name", nargs="?", type=str)
parser.add_argument(
'--noinput', '--no-input', action='store_false', dest='interactive',
"--noinput",
"--no-input",
action="store_false",
dest="interactive",
help="Do NOT prompt the user for input of any kind.",
)
def handle(self, *args, **options):
name = options['script_name']
name = options["script_name"]
if not name:
self.show_help()
@ -23,44 +26,44 @@ class Command(BaseCommand):
script = available_scripts[name]
except KeyError:
raise CommandError(
'{} is not a valid script. Run python manage.py script for a '
'list of available scripts'.format(name))
"{} is not a valid script. Run python manage.py script for a "
"list of available scripts".format(name)
)
self.stdout.write('')
if options['interactive']:
self.stdout.write("")
if options["interactive"]:
message = (
'Are you sure you want to execute the script {}?\n\n'
"Are you sure you want to execute the script {}?\n\n"
"Type 'yes' to continue, or 'no' to cancel: "
).format(name)
if input(''.join(message)) != 'yes':
if input("".join(message)) != "yes":
raise CommandError("Script cancelled.")
script['entrypoint'](self, **options)
script["entrypoint"](self, **options)
def show_help(self):
indentation = 4
self.stdout.write('')
self.stdout.write('Available scripts:')
self.stdout.write('Launch with: python manage.py <script_name>')
self.stdout.write("")
self.stdout.write("Available scripts:")
self.stdout.write("Launch with: python manage.py <script_name>")
available_scripts = self.get_scripts()
for name, script in sorted(available_scripts.items()):
self.stdout.write('')
self.stdout.write("")
self.stdout.write(self.style.SUCCESS(name))
self.stdout.write('')
for line in script['help'].splitlines():
self.stdout.write('     {}'.format(line))
self.stdout.write('')
self.stdout.write("")
for line in script["help"].splitlines():
self.stdout.write("     {}".format(line))
self.stdout.write("")
def get_scripts(self):
available_scripts = [
k for k in sorted(scripts.__dict__.keys())
if not k.startswith('__')
k for k in sorted(scripts.__dict__.keys()) if not k.startswith("__")
]
data = {}
for name in available_scripts:
module = getattr(scripts, name)
data[name] = {
'name': name,
'help': module.__doc__.strip(),
'entrypoint': module.main
"name": name,
"help": module.__doc__.strip(),
"entrypoint": module.main,
}
return data

View file

@ -7,6 +7,4 @@ class Migration(migrations.Migration):
dependencies = []
operations = [
UnaccentExtension()
]
operations = [UnaccentExtension()]

View file

@ -2,5 +2,5 @@ from rest_framework.pagination import PageNumberPagination
class FunkwhalePagination(PageNumberPagination):
page_size_query_param = 'page_size'
page_size_query_param = "page_size"
max_page_size = 50

View file

@ -9,9 +9,8 @@ from funkwhale_api.common import preferences
class ConditionalAuthentication(BasePermission):
def has_permission(self, request, view):
if preferences.get('common__api_authentication_required'):
if preferences.get("common__api_authentication_required"):
return request.user and request.user.is_authenticated
return True
@ -28,24 +27,25 @@ class OwnerPermission(BasePermission):
owner_field = 'owner'
owner_checks = ['read', 'write']
"""
perms_map = {
'GET': 'read',
'OPTIONS': 'read',
'HEAD': 'read',
'POST': 'write',
'PUT': 'write',
'PATCH': 'write',
'DELETE': 'write',
"GET": "read",
"OPTIONS": "read",
"HEAD": "read",
"POST": "write",
"PUT": "write",
"PATCH": "write",
"DELETE": "write",
}
def has_object_permission(self, request, view, obj):
method_check = self.perms_map[request.method]
owner_checks = getattr(view, 'owner_checks', ['read', 'write'])
owner_checks = getattr(view, "owner_checks", ["read", "write"])
if method_check not in owner_checks:
# check not enabled
return True
owner_field = getattr(view, 'owner_field', 'user')
owner_field = getattr(view, "owner_field", "user")
owner = operator.attrgetter(owner_field)(obj)
if owner != request.user:
raise Http404

View file

@ -17,7 +17,7 @@ def get(pref):
class StringListSerializer(serializers.BaseSerializer):
separator = ','
separator = ","
sort = True
@classmethod
@ -27,8 +27,8 @@ class StringListSerializer(serializers.BaseSerializer):
if type(value) not in [list, tuple]:
raise cls.exception(
"Cannot serialize, value {} is not a list or a tuple".format(
value))
"Cannot serialize, value {} is not a list or a tuple".format(value)
)
if cls.sort:
value = sorted(value)
@ -38,7 +38,7 @@ class StringListSerializer(serializers.BaseSerializer):
def to_python(cls, value, **kwargs):
if not value:
return []
return value.split(',')
return value.split(",")
class StringListPreference(types.BasePreferenceType):
@ -47,5 +47,5 @@ class StringListPreference(types.BasePreferenceType):
def get_api_additional_data(self):
d = super(StringListPreference, self).get_api_additional_data()
d['choices'] = self.get('choices')
d["choices"] = self.get("choices")
return d

View file

@ -8,22 +8,22 @@ from funkwhale_api.users import models
from django.contrib.auth.models import Permission
mapping = {
'dynamic_preferences.change_globalpreferencemodel': 'settings',
'music.add_importbatch': 'library',
'federation.change_library': 'federation',
"dynamic_preferences.change_globalpreferencemodel": "settings",
"music.add_importbatch": "library",
"federation.change_library": "federation",
}
def main(command, **kwargs):
for codename, user_permission in sorted(mapping.items()):
app_label, c = codename.split('.')
p = Permission.objects.get(
content_type__app_label=app_label, codename=c)
app_label, c = codename.split(".")
p = Permission.objects.get(content_type__app_label=app_label, codename=c)
users = models.User.objects.filter(
Q(groups__permissions=p) | Q(user_permissions=p)).distinct()
Q(groups__permissions=p) | Q(user_permissions=p)
).distinct()
total = users.count()
command.stdout.write('Updating {} users with {} permission...'.format(
total, user_permission
))
users.update(**{'permission_{}'.format(user_permission): True})
command.stdout.write(
"Updating {} users with {} permission...".format(total, user_permission)
)
users.update(**{"permission_{}".format(user_permission): True})

View file

@ -5,4 +5,4 @@ You can launch it just to check how it works.
def main(command, **kwargs):
command.stdout.write('Test script run successfully')
command.stdout.write("Test script run successfully")

View file

@ -17,67 +17,68 @@ class ActionSerializer(serializers.Serializer):
dangerous_actions = []
def __init__(self, *args, **kwargs):
self.queryset = kwargs.pop('queryset')
self.queryset = kwargs.pop("queryset")
if self.actions is None:
raise ValueError(
'You must declare a list of actions on '
'the serializer class')
"You must declare a list of actions on " "the serializer class"
)
for action in self.actions:
handler_name = 'handle_{}'.format(action)
assert hasattr(self, handler_name), (
'{} miss a {} method'.format(
self.__class__.__name__, handler_name)
handler_name = "handle_{}".format(action)
assert hasattr(self, handler_name), "{} miss a {} method".format(
self.__class__.__name__, handler_name
)
super().__init__(self, *args, **kwargs)
def validate_action(self, value):
if value not in self.actions:
raise serializers.ValidationError(
'{} is not a valid action. Pick one of {}.'.format(
value, ', '.join(self.actions)
"{} is not a valid action. Pick one of {}.".format(
value, ", ".join(self.actions)
)
)
return value
def validate_objects(self, value):
qs = None
if value == 'all':
return self.queryset.all().order_by('id')
if value == "all":
return self.queryset.all().order_by("id")
if type(value) in [list, tuple]:
return self.queryset.filter(pk__in=value).order_by('id')
return self.queryset.filter(pk__in=value).order_by("id")
raise serializers.ValidationError(
'{} is not a valid value for objects. You must provide either a '
'list of identifiers or the string "all".'.format(value))
"{} is not a valid value for objects. You must provide either a "
'list of identifiers or the string "all".'.format(value)
)
def validate(self, data):
dangerous = data['action'] in self.dangerous_actions
if dangerous and self.initial_data['objects'] == 'all':
dangerous = data["action"] in self.dangerous_actions
if dangerous and self.initial_data["objects"] == "all":
raise serializers.ValidationError(
'This action is to dangerous to be applied to all objects')
if self.filterset_class and 'filters' in data:
"This action is to dangerous to be applied to all objects"
)
if self.filterset_class and "filters" in data:
qs_filterset = self.filterset_class(
data['filters'], queryset=data['objects'])
data["filters"], queryset=data["objects"]
)
try:
assert qs_filterset.form.is_valid()
except (AssertionError, TypeError):
raise serializers.ValidationError('Invalid filters')
data['objects'] = qs_filterset.qs
raise serializers.ValidationError("Invalid filters")
data["objects"] = qs_filterset.qs
data['count'] = data['objects'].count()
if data['count'] < 1:
raise serializers.ValidationError(
'No object matching your request')
data["count"] = data["objects"].count()
if data["count"] < 1:
raise serializers.ValidationError("No object matching your request")
return data
def save(self):
handler_name = 'handle_{}'.format(self.validated_data['action'])
handler_name = "handle_{}".format(self.validated_data["action"])
handler = getattr(self, handler_name)
result = handler(self.validated_data['objects'])
result = handler(self.validated_data["objects"])
payload = {
'updated': self.validated_data['count'],
'action': self.validated_data['action'],
'result': result,
"updated": self.validated_data["count"],
"action": self.validated_data["action"],
"result": result,
}
return payload

View file

@ -6,13 +6,12 @@ import funkwhale_api
def get_user_agent():
return 'python-requests (funkwhale/{}; +{})'.format(
funkwhale_api.__version__,
settings.FUNKWHALE_URL
return "python-requests (funkwhale/{}; +{})".format(
funkwhale_api.__version__, settings.FUNKWHALE_URL
)
def get_session():
s = requests.Session()
s.headers['User-Agent'] = get_user_agent()
s.headers["User-Agent"] = get_user_agent()
return s

View file

@ -7,6 +7,7 @@ class ASCIIFileSystemStorage(FileSystemStorage):
"""
Convert unicode characters in name to ASCII characters.
"""
def get_valid_name(self, name):
name = unicodedata.normalize('NFKD', name).encode('ascii', 'ignore')
name = unicodedata.normalize("NFKD", name).encode("ascii", "ignore")
return super().get_valid_name(name)

View file

@ -9,13 +9,13 @@ def rename_file(instance, field_name, new_name, allow_missing_file=False):
field = getattr(instance, field_name)
current_name, extension = os.path.splitext(field.name)
new_name_with_extension = '{}{}'.format(new_name, extension)
new_name_with_extension = "{}{}".format(new_name, extension)
try:
shutil.move(field.path, new_name_with_extension)
except FileNotFoundError:
if not allow_missing_file:
raise
print('Skipped missing file', field.path)
print("Skipped missing file", field.path)
initial_path = os.path.dirname(field.name)
field.name = os.path.join(initial_path, new_name_with_extension)
instance.save()
@ -23,9 +23,7 @@ def rename_file(instance, field_name, new_name, allow_missing_file=False):
def on_commit(f, *args, **kwargs):
return transaction.on_commit(
lambda: f(*args, **kwargs)
)
return transaction.on_commit(lambda: f(*args, **kwargs))
def set_query_parameter(url, **kwargs):