Cleaning.
authorRadek Czajka <rczajka@rczajka.pl>
Mon, 16 Dec 2019 23:13:51 +0000 (00:13 +0100)
committerRadek Czajka <rczajka@rczajka.pl>
Mon, 16 Dec 2019 23:13:51 +0000 (00:13 +0100)
54 files changed:
requirements/requirements.txt
src/ajaxable/templatetags/ajaxable_tags.py
src/ajaxable/utils.py
src/annoy/admin.py
src/annoy/models.py
src/annoy/tests.py [deleted file]
src/annoy/translation.py
src/annoy/views.py [deleted file]
src/api/fields.py
src/api/models.py
src/api/renderers.py
src/api/serializers.py
src/api/tests/tests.py
src/api/urls.py
src/api/views.py
src/basicauth.py
src/catalogue/__init__.py
src/catalogue/admin.py
src/catalogue/api/fields.py
src/catalogue/api/helpers.py
src/catalogue/api/urls.py
src/catalogue/api/views.py
src/catalogue/fields.py
src/catalogue/test_utils.py
src/catalogue/tests/test_book_import.py
src/catalogue/tests/test_tags.py
src/catalogue/urls.py
src/catalogue/views.py
src/club/urls.py
src/dictionary/urls.py
src/funding/urls.py
src/infopages/urls.py
src/isbn/urls.py
src/lesmianator/urls.py
src/libraries/urls.py
src/newsletter/admin.py
src/newsletter/urls.py
src/oai/urls.py
src/opds/urls.py
src/paypal/urls.py
src/picture/api/urls.py
src/polls/urls.py
src/push/urls.py
src/reporting/urls.py
src/search/urls.py
src/social/api/urls.py
src/social/urls.py
src/suggest/urls.py
src/waiter/urls.py
src/wolnelektury/templates/base/app.html
src/wolnelektury/templates/base/superbase.html
src/wolnelektury/templates/main_page.html
src/wolnelektury/templates/widget.html
src/wolnelektury/urls.py

index b0c3c8e..f217cca 100644 (file)
@@ -1,7 +1,7 @@
 -i https://py.mdrn.pl/simple/
 
 # django
-Django==2.2.6
+Django==2.2.8
 fnpdjango==0.4
 docutils
 
index 9406481..2d980f2 100644 (file)
@@ -4,8 +4,9 @@
 from django import template
 from django.utils.encoding import force_text
 from django.utils.safestring import mark_safe
-
 from ajaxable.utils import placeholdized
+
+
 register = template.Library()
 
 
index 164feac..f8e99ce 100755 (executable)
@@ -2,23 +2,23 @@
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
 from functools import wraps
+import json
 
 from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidden
 from django.shortcuts import render
 from django.utils.encoding import force_text
 from django.utils.functional import Promise
 from django.utils.http import urlquote_plus
-import json
 from django.utils.translation import ugettext_lazy as _
 from django.views.decorators.vary import vary_on_headers
 from honeypot.decorators import verify_honeypot_value
 
 
 class LazyEncoder(json.JSONEncoder):
-    def default(self, obj):
-        if isinstance(obj, Promise):
-            return force_text(obj)
-        return obj
+    def default(self, o):
+        if isinstance(o, Promise):
+            return force_text(o)
+        return o
 
 
 def method_decorator(function_decorator):
@@ -40,8 +40,7 @@ def require_login(request):
     """Return 403 if request is AJAX. Redirect to login page if not."""
     if request.is_ajax():
         return HttpResponseForbidden('Not logged in')
-    else:
-        return HttpResponseRedirect('/uzytkownicy/zaloguj')  # next?=request.build_full_path())
+    return HttpResponseRedirect('/uzytkownicy/zaloguj')  # next?=request.build_full_path())
 
 
 def placeholdized(form):
@@ -50,7 +49,7 @@ def placeholdized(form):
     return form
 
 
-class AjaxableFormView(object):
+class AjaxableFormView:
     """Subclass this to create an ajaxable view for any form.
 
     In the subclass, provide at least form_class.
@@ -107,7 +106,7 @@ class AjaxableFormView(object):
                     response_data.update(add_args)
                 if not request.is_ajax() and response_data['redirect']:
                     return HttpResponseRedirect(urlquote_plus(
-                            response_data['redirect'], safe='/?=&'))
+                        response_data['redirect'], safe='/?=&'))
             elif request.is_ajax():
                 # Form was sent with errors. Send them back.
                 if self.form_prefix:
@@ -139,17 +138,17 @@ class AjaxableFormView(object):
         if self.placeholdize:
             form = placeholdized(form)
         context = {
-                self.formname: form,
-                "title": title,
-                "honeypot": self.honeypot,
-                "placeholdize": self.placeholdize,
-                "submit": self.submit,
-                "action": self.action,
-                "response_data": response_data,
-                "ajax_template": self.template,
-                "view_args": args,
-                "view_kwargs": kwargs,
-            }
+            self.formname: form,
+            "title": title,
+            "honeypot": self.honeypot,
+            "placeholdize": self.placeholdize,
+            "submit": self.submit,
+            "action": self.action,
+            "response_data": response_data,
+            "ajax_template": self.template,
+            "view_args": args,
+            "view_kwargs": kwargs,
+        }
         context.update(self.extra_context(request, obj))
         return render(request, template, context)
 
@@ -163,8 +162,7 @@ class AjaxableFormView(object):
             if message:
                 output = "<div class='normal-text'>" + message + "</div>" + output
             return HttpResponse(output)
-        else:
-            return HttpResponseRedirect(path)
+        return HttpResponseRedirect(path)
 
     def get_object(self, request, *args, **kwargs):
         """Override to parse view args and get some associated data."""
index 3f2bd3d..24e977e 100644 (file)
@@ -7,7 +7,7 @@ from . import models
 class BannerAdmin(TranslationAdmin):
     list_display = ['place', 'text', 'priority', 'since', 'until', 'show_members', 'staff_preview']
 
-    
+
 admin.site.register(models.Banner, BannerAdmin)
 
 
@@ -27,7 +27,7 @@ class DynamicTextInsertTextInline(admin.TabularInline):
     fields = ['text', 'image', 'own_colors', 'background_color', 'text_color']
     extra = 0
     min_num = 1
-    
+
 
 
 class DynamicTextInsertAdmin(admin.ModelAdmin):
index 5b9009b..9ed724c 100644 (file)
@@ -40,9 +40,9 @@ class Banner(models.Model):
 
         if hasattr(request, 'annoy_banner_exempt'):
             return cls.objects.none()
-        
+
         if settings.DEBUG:
-            assert place in PLACES, "Banner place `{}` must be defined in annoy.places.".format(place)
+            assert place in PLACES, f"Banner place `{place}` must be defined in annoy.places."
 
         n = now()
         banners = cls.objects.filter(
@@ -60,8 +60,8 @@ class Banner(models.Model):
             if Membership.is_active_for(request.user):
                 banners = banners.filter(show_members=True)
         return banners
-        
-        
+
+
 class DynamicTextInsert(models.Model):
     paragraphs = models.IntegerField(_('pararaphs'))
     url = models.CharField(max_length=1024)
diff --git a/src/annoy/tests.py b/src/annoy/tests.py
deleted file mode 100644 (file)
index 7ce503c..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-from django.test import TestCase
-
-# Create your tests here.
index eb17ada..2d8055a 100644 (file)
@@ -9,7 +9,4 @@ class BannerTranslationOptions(TranslationOptions):
     fields = ('text',)
 
 
-
 translator.register(models.Banner, BannerTranslationOptions)
-
-
diff --git a/src/annoy/views.py b/src/annoy/views.py
deleted file mode 100644 (file)
index 91ea44a..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-from django.shortcuts import render
-
-# Create your views here.
index b6269da..d1f9da4 100644 (file)
@@ -17,7 +17,7 @@ class AbsoluteURLField(serializers.ReadOnlyField):
         if view_args:
             for v in view_args:
                 fields = v.split(':', 1)
-                self.view_args[fields[0]] = fields[1] if len(fields)>1 else fields[0]
+                self.view_args[fields[0]] = fields[1] if len(fields) > 1 else fields[0]
 
     def to_representation(self, value):
         if self.view_name is not None:
@@ -29,7 +29,7 @@ class AbsoluteURLField(serializers.ReadOnlyField):
         return self.context['request'].build_absolute_uri(value)
 
 
-class LegacyMixin(object):
+class LegacyMixin:
     def to_representation(self, value):
         value = super(LegacyMixin, self).to_representation(value)
         non_null_fields = getattr(getattr(self, 'Meta', None), 'legacy_non_null_fields', [])
index e72aaff..28bc880 100644 (file)
@@ -30,14 +30,17 @@ def _pre_delete_handler(sender, instance, **kwargs):
         if sender == Tag:
             if instance.category in ('book', 'set'):
                 return
-            else:
-                category = instance.category
+            category = instance.category
         else:
             category = None
         content_type = ContentType.objects.get_for_model(sender)
         Deleted.objects.create(
-            content_type=content_type, object_id=instance.id, created_at=instance.created_at, category=category,
-            slug=instance.slug)
+            content_type=content_type,
+            object_id=instance.id,
+            created_at=instance.created_at,
+            category=category,
+            slug=instance.slug
+        )
 pre_delete.connect(_pre_delete_handler)
 
 
@@ -57,7 +60,6 @@ class BookUserData(models.Model):
         instance.complete = state == 'complete'
         instance.save()
         return instance
-from django.conf import settings
 
 
 KEY_SIZE = 18
@@ -85,7 +87,10 @@ class Consumer(models.Model):
     key = models.CharField(max_length=KEY_SIZE)
     secret = models.CharField(max_length=SECRET_SIZE)
     status = models.CharField(max_length=16, choices=CONSUMER_STATES, default='pending')
-    user = models.ForeignKey(settings.AUTH_USER_MODEL, models.CASCADE, null=True, blank=True, related_name='consumers')
+    user = models.ForeignKey(
+        settings.AUTH_USER_MODEL, models.CASCADE,
+        null=True, blank=True, related_name='consumers'
+    )
 
     def __str__(self):
         return "Consumer %s with key %s" % (self.name, self.key)
@@ -101,7 +106,10 @@ class Token(models.Model):
     token_type = models.IntegerField(choices=TOKEN_TYPES)
     timestamp = models.IntegerField()
     is_approved = models.BooleanField(default=False)
-    user = models.ForeignKey(settings.AUTH_USER_MODEL, models.CASCADE, null=True, blank=True, related_name='tokens')
+    user = models.ForeignKey(
+        settings.AUTH_USER_MODEL, models.CASCADE,
+        null=True, blank=True, related_name='tokens'
+    )
     consumer = models.ForeignKey(Consumer, models.CASCADE)
 
     def __str__(self):
index 57edec3..3f742db 100644 (file)
@@ -11,4 +11,3 @@ class LegacyXMLRenderer(XMLRenderer):
 
     item_tag_name = 'resource'
     root_tag_name = 'response'
-
index 237a155..eb6994c 100644 (file)
@@ -3,7 +3,7 @@
 #
 from django.contrib.auth.models import User
 from rest_framework import serializers
-from .fields import UserPremiumField, AbsoluteURLField, ThumbnailField
+from .fields import UserPremiumField
 from .models import BookUserData
 
 
index e17db29..f85a061 100644 (file)
@@ -2,25 +2,25 @@
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
 from base64 import b64encode
-from os import path
 import hashlib
 import hmac
-import json
 from io import BytesIO
+import json
+from os import path
 from time import time
+from unittest.mock import patch
 from urllib.parse import quote, urlencode, parse_qs
 
 from django.contrib.auth.models import User
 from django.core.files.uploadedfile import SimpleUploadedFile
 from django.test import TestCase
 from django.test.utils import override_settings
-from unittest.mock import patch
-from api.models import Consumer, Token
 
 from catalogue.models import Book, Tag
 from picture.forms import PictureImportForm
 from picture.models import Picture
 import picture.tests
+from api.models import Consumer, Token
 
 
 @override_settings(
@@ -275,7 +275,11 @@ class OAuth1Tests(ApiTest):
 
         # Request token authorization.
         self.client.login(username='test', password='test')
-        response = self.client.get('/api/oauth/authorize/?oauth_token=%s&oauth_callback=test://oauth.callback/' % request_token)
+        response = self.client.get(
+            '/api/oauth/authorize/?oauth_token=%s&oauth_callback=test://oauth.callback/' % (
+                request_token,
+            )
+        )
         post_data = response.context['form'].initial
 
         response = self.client.post('/api/oauth/authorize/?' + urlencode(post_data))
index 536d3fe..4fb321a 100644 (file)
@@ -1,7 +1,7 @@
 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
-from django.conf.urls import url, include
+from django.urls import path, include
 from django.views.decorators.csrf import csrf_exempt
 from django.views.generic import TemplateView
 import catalogue.views
@@ -10,31 +10,31 @@ from . import views
 
 
 urlpatterns = [
-    url(r'^oauth/request_token/$', csrf_exempt(views.OAuth1RequestTokenView.as_view())),
-    url(r'^oauth/authorize/$', views.oauth_user_auth, name='oauth_user_auth'),
-    url(r'^oauth/access_token/$', csrf_exempt(views.OAuth1AccessTokenView.as_view())),
+    path('oauth/request_token/', csrf_exempt(views.OAuth1RequestTokenView.as_view())),
+    path('oauth/authorize/', views.oauth_user_auth, name='oauth_user_auth'),
+    path('oauth/access_token/', csrf_exempt(views.OAuth1AccessTokenView.as_view())),
 
-    url(r'^$', TemplateView.as_view(template_name='api/main.html'), name='api'),
+    path('', TemplateView.as_view(template_name='api/main.html'), name='api'),
 
     # info boxes (used by mobile app)
-    url(r'book/(?P<book_id>\d*?)/info\.html$', catalogue.views.book_info),
-    url(r'tag/(?P<tag_id>\d*?)/info\.html$', catalogue.views.tag_info),
+    path('book/<int:book_id>/info.html', catalogue.views.book_info),
+    path('tag/<int:tag_id>/info.html', catalogue.views.tag_info),
 
     # reading data
-    url(r'^reading/(?P<slug>[a-z0-9-]+)/$',
-        piwik_track_view(views.BookUserDataView.as_view()),
-        name='api_reading'),
-    url(r'^reading/(?P<slug>[a-z0-9-]+)/(?P<state>[a-z]+)/$',
-        piwik_track_view(views.BookUserDataView.as_view()),
-        name='api_reading'),
-    url(r'^username/$',
-        piwik_track_view(views.UserView.as_view()),
-        name='api_username'),
+    path('reading/<slug:slug>/',
+         piwik_track_view(views.BookUserDataView.as_view()),
+         name='api_reading'),
+    path('reading/<slug:slug>/<slug:state>/',
+         piwik_track_view(views.BookUserDataView.as_view()),
+         name='api_reading'),
+    path('username/',
+         piwik_track_view(views.UserView.as_view()),
+         name='api_username'),
 
-    url(r'^blog$',
-        piwik_track_view(views.BlogView.as_view())),
+    path('blog',
+         piwik_track_view(views.BlogView.as_view())),
 
-    url(r'^pictures/', include('picture.api.urls')),
-    url(r'^', include('social.api.urls')),
-    url(r'^', include('catalogue.api.urls')),
+    path('pictures/', include('picture.api.urls')),
+    path('', include('social.api.urls')),
+    path('', include('catalogue.api.urls')),
 ]
index 69f9b8b..6762fb1 100644 (file)
@@ -10,13 +10,12 @@ from django.views.generic.base import View
 from oauthlib.common import urlencode
 from oauthlib.oauth1 import RequestTokenEndpoint, AccessTokenEndpoint
 from oauthlib.oauth1 import AuthorizationEndpoint, OAuth1Error
-from api.models import KEY_SIZE, SECRET_SIZE
 from rest_framework.permissions import IsAuthenticated
 from rest_framework.response import Response
 from rest_framework.views import APIView
-from rest_framework.generics import ListAPIView, RetrieveAPIView, get_object_or_404
+from rest_framework.generics import RetrieveAPIView, get_object_or_404
 from catalogue.models import Book
-from .models import BookUserData
+from .models import BookUserData, KEY_SIZE, SECRET_SIZE
 from . import serializers
 from .request_validator import PistonRequestValidator
 from .utils import oauthlib_request, oauthlib_response, vary_on_auth
@@ -86,7 +85,7 @@ def oauth_user_auth(request):
 
         return render(request, 'oauth/authorize_token.html', {'form': form})
 
-    elif request.method == "POST":
+    if request.method == "POST":
         try:
             response = oauthlib_response(
                 endpoint.create_authorization_response(
index 1275390..b4acb46 100644 (file)
@@ -44,7 +44,7 @@ def view_or_basicauth(view, request, test_func, realm="", *args, **kwargs):
     response.status_code = 401
     response['WWW-Authenticate'] = 'Basic realm="%s"' % realm
     return response
-    
+
 
 #
 def logged_in_or_basicauth(realm=""):
index 1290f81..da120b5 100644 (file)
@@ -2,7 +2,7 @@
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
 import logging
-from django.conf import settings as settings
+from django.conf import settings
 from django.utils.module_loading import import_string
 from catalogue.utils import AppSettings
 
@@ -16,11 +16,11 @@ class Settings(AppSettings):
     # PDF needs TeXML + XeLaTeX, MOBI needs Calibre.
     DONT_BUILD = {'pdf', 'mobi'}
     FORMAT_ZIPS = {
-            'epub': 'wolnelektury_pl_epub',
-            'pdf': 'wolnelektury_pl_pdf',
-            'mobi': 'wolnelektury_pl_mobi',
-            'fb2': 'wolnelektury_pl_fb2',
-        }
+        'epub': 'wolnelektury_pl_epub',
+        'pdf': 'wolnelektury_pl_pdf',
+        'mobi': 'wolnelektury_pl_mobi',
+        'fb2': 'wolnelektury_pl_fb2',
+    }
 
     REDAKCJA_URL = "http://redakcja.wolnelektury.pl"
     GOOD_LICENSES = {r'CC BY \d\.\d', r'CC BY-SA \d\.\d'}
@@ -42,7 +42,10 @@ class Settings(AppSettings):
         for format_ in ['epub', 'pdf', 'mobi', 'fb2']:
             attname = 'ALL_%s_ZIP' % format_.upper()
             if hasattr(settings, attname):
-                logging.warn("%s is deprecated, use CATALOGUE_FORMAT_ZIPS[%s] instead", attname, format_)
+                logging.warn(
+                    "%s is deprecated, use CATALOGUE_FORMAT_ZIPS[%s] instead",
+                    attname, format_
+                )
                 value[format_] = getattr(settings, attname)
         return value
 
index 9008df1..88377e7 100644 (file)
@@ -2,8 +2,6 @@
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
 from django.contrib import admin
-from django import forms
-
 from catalogue.models import Tag, Book, Fragment, BookMedia, Collection, Source
 
 
@@ -29,7 +27,9 @@ class MediaInline(admin.TabularInline):
 
 
 class BookAdmin(admin.ModelAdmin):
-    list_display = ('title', 'slug', 'created_at', 'has_epub_file', 'has_html_file', 'has_description',)
+    list_display = (
+        'title', 'slug', 'created_at', 'has_epub_file', 'has_html_file', 'has_description',
+    )
     search_fields = ('title',)
     ordering = ('title',)
 
index 80de4ab..d95c3a8 100644 (file)
@@ -15,7 +15,9 @@ class BookLiked(serializers.ReadOnlyField):
         request = self.context['request']
         if not hasattr(request, 'liked_books'):
             if request.user.is_authenticated:
-                request.liked_books = set(Book.tagged.with_any(request.user.tag_set.all()).values_list('id', flat=True))
+                request.liked_books = set(
+                    Book.tagged.with_any(request.user.tag_set.all()).values_list('id', flat=True)
+                )
             else:
                 request.liked_books = None
         if request.liked_books is not None:
index 6813e03..7971268 100644 (file)
@@ -20,6 +20,4 @@ def books_after(books, after, new_api):
 def order_books(books, new_api):
     if new_api:
         return books.order_by('sort_key_author', 'sort_key', 'id')
-    else:
-        return books.order_by('slug')
-
+    return books.order_by('slug')
index 0f2343d..2e5a9be 100644 (file)
@@ -1,7 +1,7 @@
 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
-from django.conf.urls import include, url
+from django.urls import path, re_path
 from stats.utils import piwik_track_view
 from . import views
 
@@ -12,67 +12,67 @@ paginate_re = r'(?:after/(?P<after>[a-z0-9-]+)/)?(?:count/(?P<count>[0-9]+)/)?$'
 
 urlpatterns = [
     # books by collections
-    url(r'^collections/$',
-        piwik_track_view(views.CollectionList.as_view()),
-        name="catalogue_api_collections"),
-    url(r'^collections/(?P<slug>[^/]+)/$',
-        piwik_track_view(views.CollectionDetail.as_view()),
-        name="collection-detail"),
+    path('collections/',
+         piwik_track_view(views.CollectionList.as_view()),
+         name="catalogue_api_collections"),
+    path('collections/<slug:slug>/',
+         piwik_track_view(views.CollectionDetail.as_view()),
+         name="collection-detail"),
 
-    url(tags_re + r'books/' + paginate_re,
-        piwik_track_view(views.BookList.as_view()),
-        name='catalogue_api_book_list'),
-    url(tags_re + r'parent_books/' + paginate_re,
-        piwik_track_view(views.BookList.as_view()),
-        {"top_level": True}, name='catalogue_api_parent_book_list'),
-    url(tags_re + r'audiobooks/' + paginate_re,
-        piwik_track_view(views.BookList.as_view()),
-        {"audiobooks": True}, name='catalogue_api_audiobook_list'),
-    url(tags_re + r'daisy/' + paginate_re,
-        piwik_track_view(views.BookList.as_view()),
-        {"daisy": True}, name='catalogue_api_daisy_list'),
-    url(r'^recommended/' + paginate_re,
-        piwik_track_view(views.BookList.as_view()),
-        {"recommended": True}, name='catalogue_api_recommended_list'),
-    url(r'^newest/$',
-        piwik_track_view(views.BookList.as_view()),
-        {"newest": True, "top_level": True, "count": 20},
-        name='catalogue_api_newest_list'),
+    re_path(tags_re + r'books/' + paginate_re,
+            piwik_track_view(views.BookList.as_view()),
+            name='catalogue_api_book_list'),
+    re_path(tags_re + r'parent_books/' + paginate_re,
+            piwik_track_view(views.BookList.as_view()),
+            {"top_level": True}, name='catalogue_api_parent_book_list'),
+    re_path(tags_re + r'audiobooks/' + paginate_re,
+            piwik_track_view(views.BookList.as_view()),
+            {"audiobooks": True}, name='catalogue_api_audiobook_list'),
+    re_path(tags_re + r'daisy/' + paginate_re,
+            piwik_track_view(views.BookList.as_view()),
+            {"daisy": True}, name='catalogue_api_daisy_list'),
+    re_path(r'^recommended/' + paginate_re,
+            piwik_track_view(views.BookList.as_view()),
+            {"recommended": True}, name='catalogue_api_recommended_list'),
+    path('newest/',
+         piwik_track_view(views.BookList.as_view()),
+         {"newest": True, "top_level": True, "count": 20},
+         name='catalogue_api_newest_list'),
 
-    url(r'^books/(?P<slug>[^/]+)/$',
-        piwik_track_view(views.BookDetail.as_view()),
-        name='catalogue_api_book'),
+    path('books/<slug:slug>/',
+         piwik_track_view(views.BookDetail.as_view()),
+         name='catalogue_api_book'),
 
-    url(tags_re + r'ebooks/' + paginate_re,
-        piwik_track_view(views.EbookList.as_view()),
-        name='catalogue_api_ebook_list'),
-    url(tags_re + r'parent_ebooks/' + paginate_re,
-        piwik_track_view(views.EbookList.as_view()),
-        {"top_level": True},
-        name='catalogue_api_parent_ebook_list'),
+    re_path(tags_re + r'ebooks/' + paginate_re,
+            piwik_track_view(views.EbookList.as_view()),
+            name='catalogue_api_ebook_list'),
+    re_path(tags_re + r'parent_ebooks/' + paginate_re,
+            piwik_track_view(views.EbookList.as_view()),
+            {"top_level": True},
+            name='catalogue_api_parent_ebook_list'),
 
-    url(r'^filter-books/$',
-        piwik_track_view(views.FilterBookList.as_view()),
-        name='catalogue_api_filter_books'),
+    path('filter-books/',
+         piwik_track_view(views.FilterBookList.as_view()),
+         name='catalogue_api_filter_books'),
 
-    url(r'^epub/(?P<slug>[a-z0-9-]+)/$',
-        piwik_track_view(views.EpubView.as_view()),
-        name='catalogue_api_epub'),
+    path('epub/<slug:slug>/',
+         piwik_track_view(views.EpubView.as_view()),
+         name='catalogue_api_epub'),
 
-    url(r'^preview/$',
-        piwik_track_view(views.Preview.as_view()),
-        name='catalogue_api_preview'),
+    path('preview/',
+         piwik_track_view(views.Preview.as_view()),
+         name='catalogue_api_preview'),
 
-    url(r'^(?P<tags>(?:(?:[a-z0-9-]+/){2}){1,6})fragments/$',
-        piwik_track_view(views.FragmentList.as_view())),
-    url(r'^books/(?P<book>[a-z0-9-]+)/fragments/(?P<anchor>[a-z0-9-]+)/$',
-        piwik_track_view(views.FragmentView.as_view()),
-        name="catalogue_api_fragment"),
+    re_path(r'^(?P<tags>(?:(?:[a-z0-9-]+/){2}){1,6})fragments/$',
+            piwik_track_view(views.FragmentList.as_view())),
+    path('books/<slug:book>/fragments/<slug:anchor>/',
+         piwik_track_view(views.FragmentView.as_view()),
+         name="catalogue_api_fragment"),
 
-    url(r'^(?P<category>[a-z]+)s/$',
-        piwik_track_view(views.TagCategoryView.as_view()),
-        name='catalogue_api_tag_list'),
-    url(r'^(?P<category>[a-z]+)s/(?P<slug>[a-z0-9-]+)/$',
-        piwik_track_view(views.TagView.as_view()),
-        name="catalogue_api_tag"),
+    path('<slug:category>s/',
+         piwik_track_view(views.TagCategoryView.as_view()),
+         name='catalogue_api_tag_list'),
+    path('<slug:category>s/<slug:slug>/',
+         piwik_track_view(views.TagView.as_view()),
+         name="catalogue_api_tag"),
 ]
index 34971c4..c70a73e 100644 (file)
@@ -11,14 +11,14 @@ from rest_framework.response import Response
 from rest_framework import status
 from api.handlers import read_tags
 from api.utils import vary_on_auth
-from club.models import Membership
-from .helpers import books_after, order_books
-from . import serializers
 from catalogue.forms import BookImportForm
 from catalogue.models import Book, Collection, Tag, Fragment, BookMedia
 from catalogue.models.tag import prefetch_relations
+from club.models import Membership
 from club.permissions import IsClubMember
 from wolnelektury.utils import re_escape
+from .helpers import books_after, order_books
+from . import serializers
 
 
 book_tag_categories = ['author', 'epoch', 'kind', 'genre']
index 46cde23..be4ce8a 100644 (file)
@@ -133,8 +133,9 @@ class BuildTxt(BuildEbook):
 class BuildPdf(BuildEbook):
     @staticmethod
     def transform(wldoc, fieldfile):
-        return wldoc.as_pdf(morefloats=settings.LIBRARIAN_PDF_MOREFLOATS, cover=True,
-                            ilustr_path=gallery_path(wldoc.book_info.url.slug), customizations=['notoc'])
+        return wldoc.as_pdf(
+            morefloats=settings.LIBRARIAN_PDF_MOREFLOATS, cover=True,
+            ilustr_path=gallery_path(wldoc.book_info.url.slug), customizations=['notoc'])
 
     def build(self, fieldfile):
         BuildEbook.build(self, fieldfile)
@@ -203,8 +204,9 @@ class BuildHtml(BuildEbook):
                     if lang == settings.LANGUAGE_CODE:
                         # Allow creating themes if book in default language.
                         tag, created = Tag.objects.get_or_create(
-                                            slug=slugify(theme_name),
-                                            category='theme')
+                            slug=slugify(theme_name),
+                            category='theme'
+                        )
                         if created:
                             tag.name = theme_name
                             setattr(tag, "name_%s" % lang, theme_name)
@@ -215,7 +217,10 @@ class BuildHtml(BuildEbook):
                     elif lang is not None:
                         # Don't create unknown themes in non-default languages.
                         try:
-                            tag = Tag.objects.get(category='theme', **{"name_%s" % lang: theme_name})
+                            tag = Tag.objects.get(
+                                category='theme',
+                                **{"name_%s" % lang: theme_name}
+                            )
                         except Tag.DoesNotExist:
                             pass
                         else:
@@ -227,7 +232,12 @@ class BuildHtml(BuildEbook):
                 short_text = truncate_html_words(text, 15)
                 if text == short_text:
                     short_text = ''
-                new_fragment = Fragment.objects.create(anchor=fragment.id, book=book, text=text, short_text=short_text)
+                new_fragment = Fragment.objects.create(
+                    anchor=fragment.id,
+                    book=book,
+                    text=text,
+                    short_text=short_text
+                )
 
                 new_fragment.save()
                 new_fragment.tags = set(meta_tags + themes)
index a6e69db..6bc5569 100644 (file)
@@ -4,11 +4,11 @@
 from os.path import abspath, dirname, join
 import tempfile
 from traceback import extract_stack
+from django.conf import settings
 from django.test import TestCase
 from django.test.utils import override_settings
 from slugify import slugify
 from librarian import WLURI
-from django.conf import settings
 
 
 @override_settings(
@@ -17,8 +17,8 @@ from django.conf import settings
     NO_SEARCH_INDEX=True,
     CELERY_TASK_ALWAYS_EAGER=True,
     CACHES={
-            'default': {'BACKEND': 'django.core.cache.backends.dummy.DummyCache'},
-        },
+        'default': {'BACKEND': 'django.core.cache.backends.dummy.DummyCache'},
+    },
     SOLR=settings.SOLR_TEST,
 )
 class WLTestCase(TestCase):
@@ -28,7 +28,7 @@ class WLTestCase(TestCase):
     longMessage = True
 
 
-class PersonStub(object):
+class PersonStub:
 
     def __init__(self, first_names, last_name):
         self.first_names = first_names
@@ -38,7 +38,7 @@ class PersonStub(object):
         return " ".join(self.first_names + (self.last_name,))
 
 
-class BookInfoStub(object):
+class BookInfoStub:
     _empty_fields = ['cover_url', 'variant_of']
     # allow single definition for multiple-value fields
     _salias = {
@@ -59,10 +59,9 @@ class BookInfoStub(object):
         except KeyError as e:
             if key in self._empty_fields:
                 return None
-            elif key in self._salias:
+            if key in self._salias:
                 return [getattr(self, self._salias[key])]
-            else:
-                raise AttributeError(e)
+            raise AttributeError(e)
 
     def to_dict(self):
         return dict((key, str(value)) for key, value in self.__dict.items())
index 9ad22a4..f8900c8 100644 (file)
@@ -25,10 +25,10 @@ class BookImportLogicTests(WLTestCase):
         )
 
         self.expected_tags = [
-           ('author', 'jim-lazy'),
-           ('genre', 'x-genre'),
-           ('epoch', 'x-epoch'),
-           ('kind', 'x-kind'),
+            ('author', 'jim-lazy'),
+            ('genre', 'x-genre'),
+            ('epoch', 'x-epoch'),
+            ('kind', 'x-kind'),
         ]
         self.expected_tags.sort()
 
@@ -97,8 +97,14 @@ class BookImportLogicTests(WLTestCase):
         """
 
         book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info)
-        self.assertTrue([('theme', 'love')],
-                     book.fragments.all()[0].tags.filter(category='theme').values_list('category', 'slug'))
+        self.assertEqual(
+            [('theme', 'love')],
+            list(
+                book.fragments.all()[0].tags.filter(
+                    category='theme'
+                ).values_list('category', 'slug')
+            )
+        )
 
     def test_book_with_no_theme(self):
         """ fragments with no themes shouldn't be created at all """
@@ -180,10 +186,10 @@ class BookImportLogicTests(WLTestCase):
         self.book_info.epochs = self.book_info.epoch, 'Y-Epoch',
 
         self.expected_tags.extend([
-           ('author', 'joe-dilligent'),
-           ('genre', 'y-genre'),
-           ('epoch', 'y-epoch'),
-           ('kind', 'y-kind'),
+            ('author', 'joe-dilligent'),
+            ('genre', 'y-genre'),
+            ('epoch', 'y-epoch'),
+            ('kind', 'y-kind'),
         ])
         self.expected_tags.sort()
 
@@ -287,10 +293,10 @@ class TreeImportTest(WLTestCase):
 
     def test_ok(self):
         self.assertEqual(
-                list(self.client.get('/katalog/gatunek/x-genre/').context['object_list']),
-                [self.parent],
-                "There should be only parent on common tag page."
-            )
+            list(self.client.get('/katalog/gatunek/x-genre/').context['object_list']),
+            [self.parent],
+            "There should be only parent on common tag page."
+        )
         # pies = models.Tag.objects.get(slug='pies')
         themes = self.parent.related_themes()
         self.assertEqual(len(themes), 1, "There should be child theme in parent theme counter.")
@@ -308,10 +314,10 @@ class TreeImportTest(WLTestCase):
         models.Book.from_text_and_meta(
             ContentFile(child_text), self.child_info, overwrite=True)
         self.assertEqual(
-                list(self.client.get('/katalog/gatunek/x-genre/').context['object_list']),
-                [self.parent],
-                "There should only be parent on common tag page."
-            )
+            list(self.client.get('/katalog/gatunek/x-genre/').context['object_list']),
+            [self.parent],
+            "There should only be parent on common tag page."
+        )
         # pies = models.Tag.objects.get(slug='pies')
         # kot = models.Tag.objects.get(slug='kot')
         self.assertEqual(len(self.parent.related_themes()), 2,
@@ -396,7 +402,7 @@ class MultilingualBookImportTest(WLTestCase):
         models.Book.from_text_and_meta(ContentFile(book_text), self.eng_info)
 
         self.assertEqual(
-            set([b.language for b in models.Book.objects.all()]),
+            {b.language for b in models.Book.objects.all()},
             {'pol', 'eng'},
             'Books imported in wrong languages.'
         )
index 29acd4a..92845e2 100644 (file)
@@ -96,8 +96,9 @@ class TagRelatedTagsTests(WLTestCase):
                 </akap></opowiadanie></utwor>
                 """ % info.title
             book = models.Book.from_text_and_meta(
-                    ContentFile(book_text.encode('utf-8')),
-                    info)
+                ContentFile(book_text.encode('utf-8')),
+                info
+            )
             book.save()
 
         tag_empty = models.Tag(name='Empty tag', slug='empty', category='author')
index ac551b9..27fddc2 100644 (file)
@@ -1,7 +1,7 @@
 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
-from django.conf.urls import url
+from django.urls import path, re_path
 from django.db.models import Max
 from django.views.generic import ListView, RedirectView
 from catalogue.feeds import AudiobookFeed
@@ -10,72 +10,71 @@ from catalogue import views
 import picture.views
 
 
-SLUG = r'[a-z0-9-]*'
-
 urlpatterns = [
-    url(r'^obraz/strona/$', picture.views.picture_page, name='picture_page'),
+    path('obraz/strona/', picture.views.picture_page, name='picture_page'),
     # pictures - currently pictures are coupled with catalogue, hence the url is here
-    url(r'^obraz/$', picture.views.picture_list_thumb, name='picture_list_thumb'),
-    url(r'^obraz/(?P<slug>%s).html$' % SLUG, picture.views.picture_viewer, name='picture_viewer'),
-    url(r'^obraz/(?P<slug>%s)/$' % SLUG, picture.views.picture_detail, name='picture_detail'),
+    path('obraz/', picture.views.picture_list_thumb, name='picture_list_thumb'),
+    path('obraz/<slug:slug>.html', picture.views.picture_viewer, name='picture_viewer'),
+    path('obraz/<slug:slug>/', picture.views.picture_detail, name='picture_detail'),
 
     # old search page - redirected
-    url(r'^szukaj/$', RedirectView.as_view(
-            url='/szukaj/', query_string=True, permanent=True)),
+    path('szukaj/', RedirectView.as_view(
+        url='/szukaj/', query_string=True, permanent=True)),
 
-    url(r'^$', views.catalogue, name='catalogue'),
+    path('', views.catalogue, name='catalogue'),
 
-    url(r'^autor/$', views.tag_catalogue, {'category': 'author'}, name='author_catalogue'),
-    url(r'^epoka/$', views.tag_catalogue, {'category': 'epoch'}, name='epoch_catalogue'),
-    url(r'^gatunek/$', views.tag_catalogue, {'category': 'genre'}, name='genre_catalogue'),
-    url(r'^rodzaj/$', views.tag_catalogue, {'category': 'kind'}, name='kind_catalogue'),
-    url(r'^motyw/$', views.tag_catalogue, {'category': 'theme'}, name='theme_catalogue'),
+    path('autor/', views.tag_catalogue, {'category': 'author'}, name='author_catalogue'),
+    path('epoka/', views.tag_catalogue, {'category': 'epoch'}, name='epoch_catalogue'),
+    path('gatunek/', views.tag_catalogue, {'category': 'genre'}, name='genre_catalogue'),
+    path('rodzaj/', views.tag_catalogue, {'category': 'kind'}, name='kind_catalogue'),
+    path('motyw/', views.tag_catalogue, {'category': 'theme'}, name='theme_catalogue'),
 
-    url(r'^galeria/$', views.gallery, name='gallery'),
-    url(r'^kolekcje/$', views.collections, name='catalogue_collections'),
+    path('galeria/', views.gallery, name='gallery'),
+    path('kolekcje/', views.collections, name='catalogue_collections'),
 
-    url(r'^lektury/$', views.literature, name='book_list'),
-    url(r'^lektury/(?P<slug>[a-zA-Z0-9-]+)/$', views.collection, name='collection'),
-    url(r'^audiobooki/$', views.audiobooks, name='audiobook_list'),
-    url(r'^daisy/$', views.daisy_list, name='daisy_list'),
-    url(r'^nowe/$', ListView.as_view(
+    path('lektury/', views.literature, name='book_list'),
+    path('lektury/<slug:slug>/', views.collection, name='collection'),
+    path('audiobooki/', views.audiobooks, name='audiobook_list'),
+    path('daisy/', views.daisy_list, name='daisy_list'),
+    path('nowe/', ListView.as_view(
         queryset=Book.objects.filter(parent=None).order_by('-created_at'),
         template_name='catalogue/recent_list.html'), name='recent_list'),
-    url(r'^nowe/audiobooki/$', ListView.as_view(
+    path('nowe/audiobooki/', ListView.as_view(
         queryset=Book.objects.filter(media__type='ogg').annotate(m=Max('media__uploaded_at')).order_by('-m'),
         template_name='catalogue/recent_audiobooks_list.html'), name='recent_audiobooks_list'),
-    url(r'^nowe/daisy/$', ListView.as_view(
+    path('nowe/daisy/', ListView.as_view(
         queryset=Book.objects.filter(media__type='daisy').annotate(m=Max('media__uploaded_at')).order_by('-m'),
         template_name='catalogue/recent_daisy_list.html'), name='recent_daisy_list'),
 
-    url(r'^custompdf/(?P<slug>%s)/$' % SLUG, views.CustomPDFFormView(), name='custom_pdf_form'),
+    path('custompdf/<slug:slug>/', views.CustomPDFFormView(), name='custom_pdf_form'),
 
-    url(r'^audiobooki/(?P<type>mp3|ogg|daisy|all).xml$', AudiobookFeed(), name='audiobook_feed'),
+    re_path(r'^audiobooki/(?P<type>mp3|ogg|daisy|all).xml$', AudiobookFeed(), name='audiobook_feed'),
 
-    url(r'^pobierz/(?P<key>.*)/(?P<slug>%s).(?P<format_>[a-z0-9]*)$' % SLUG, views.embargo_link, name='embargo_link'),
+    path('pobierz/<key>/<slug:slug>.<slug:format_>', views.embargo_link, name='embargo_link'),
 
     # zip
-    url(r'^zip/pdf\.zip$', views.download_zip, {'format': 'pdf', 'slug': None}, 'download_zip_pdf'),
-    url(r'^zip/epub\.zip$', views.download_zip, {'format': 'epub', 'slug': None}, 'download_zip_epub'),
-    url(r'^zip/mobi\.zip$', views.download_zip, {'format': 'mobi', 'slug': None}, 'download_zip_mobi'),
-    url(r'^zip/mp3/(?P<slug>%s)\.zip' % SLUG, views.download_zip, {'format': 'mp3'}, 'download_zip_mp3'),
-    url(r'^zip/ogg/(?P<slug>%s)\.zip' % SLUG, views.download_zip, {'format': 'ogg'}, 'download_zip_ogg'),
+    path('zip/pdf.zip', views.download_zip, {'format': 'pdf', 'slug': None}, 'download_zip_pdf'),
+    path('zip/epub.zip', views.download_zip, {'format': 'epub', 'slug': None}, 'download_zip_epub'),
+    path('zip/mobi.zip', views.download_zip, {'format': 'mobi', 'slug': None}, 'download_zip_mobi'),
+    path('zip/mp3/<slug:slug>.zip', views.download_zip, {'format': 'mp3'}, 'download_zip_mp3'),
+    path('zip/ogg/<slug:slug>.zip', views.download_zip, {'format': 'ogg'}, 'download_zip_ogg'),
 
     # Public interface. Do not change this URLs.
-    url(r'^lektura/(?P<slug>%s)\.html$' % SLUG, views.book_text, name='book_text'),
-    url(r'^lektura/(?P<slug>%s)/audiobook/$' % SLUG, views.player, name='book_player'),
-    url(r'^lektura/(?P<slug>%s)/$' % SLUG, views.book_detail, name='book_detail'),
-    url(r'^lektura/(?P<slug>%s)/motyw/(?P<theme_slug>[a-zA-Z0-9-]+)/$' % SLUG,
-        views.book_fragments, name='book_fragments'),
+    path('lektura/<slug:slug>.html', views.book_text, name='book_text'),
+    path('lektura/<slug:slug>/audiobook/', views.player, name='book_player'),
+    path('lektura/<slug:slug>/', views.book_detail, name='book_detail'),
+    path('lektura/<slug:slug>/motyw/<slug:theme_slug>/',
+         views.book_fragments, name='book_fragments'),
 
-    url(r'^okladka-ridero/(?P<slug>%s).png$' % SLUG, views.ridero_cover),
-    url(r'^isbn/(?P<book_format>(pdf|epub|mobi|txt|html))/(?P<slug>%s)/' % SLUG, views.get_isbn),
+    path('okladka-ridero/<slug:slug>.png', views.ridero_cover),
+    path('isbn/<slug:book_format>/<slug:slug>/', views.get_isbn),
 
     # This should be the last pattern.
-    url(r'^galeria/(?P<tags>[a-zA-Z0-9-/]*)/$', views.tagged_object_list, {'list_type': 'gallery'},
+    re_path(r'^galeria/(?P<tags>[a-zA-Z0-9-/]*)/$', views.tagged_object_list, {'list_type': 'gallery'},
         name='tagged_object_list_gallery'),
-    url(r'^audiobooki/(?P<tags>[a-zA-Z0-9-/]*)/$', views.tagged_object_list, {'list_type': 'audiobooks'},
+    re_path(r'^audiobooki/(?P<tags>[a-zA-Z0-9-/]*)/$', views.tagged_object_list, {'list_type': 'audiobooks'},
         name='tagged_object_list_audiobooks'),
-    url(r'^(?P<tags>[a-zA-Z0-9-/]*)/$', views.tagged_object_list, {'list_type': 'books'},
+    re_path(r'^(?P<tags>[a-zA-Z0-9-/]*)/$', views.tagged_object_list, {'list_type': 'books'},
         name='tagged_object_list'),
+
 ]
index 66a2b91..2c6692f 100644 (file)
@@ -81,10 +81,13 @@ def differentiate_tags(request, tags, ambiguous_slugs):
         })
     return render(
         request,
-        'catalogue/differentiate_tags.html', {'tags': tags, 'options': options, 'unparsed': ambiguous_slugs[1:]})
+        'catalogue/differentiate_tags.html',
+        {'tags': tags, 'options': options, 'unparsed': ambiguous_slugs[1:]}
+    )
 
 
-def object_list(request, objects, fragments=None, related_tags=None, tags=None, list_type='books', extra=None):
+def object_list(request, objects, fragments=None, related_tags=None, tags=None,
+                list_type='books', extra=None):
     if not tags:
         tags = []
     tag_ids = [tag.pk for tag in tags]
@@ -94,7 +97,9 @@ def object_list(request, objects, fragments=None, related_tags=None, tags=None,
         related_tag_lists.append(related_tags)
     else:
         related_tag_lists.append(
-            Tag.objects.usage_for_queryset(objects, counts=True).exclude(category='set').exclude(pk__in=tag_ids))
+            Tag.objects.usage_for_queryset(
+                objects, counts=True
+            ).exclude(category='set').exclude(pk__in=tag_ids))
     if not (extra and extra.get('theme_is_set')):
         if fragments is None:
             if list_type == 'gallery':
@@ -102,7 +107,9 @@ def object_list(request, objects, fragments=None, related_tags=None, tags=None,
             else:
                 fragments = Fragment.objects.filter(book__in=objects)
         related_tag_lists.append(
-            Tag.objects.usage_for_queryset(fragments, counts=True).filter(category='theme').exclude(pk__in=tag_ids)
+            Tag.objects.usage_for_queryset(
+                fragments, counts=True
+            ).filter(category='theme').exclude(pk__in=tag_ids)
             .only('name', 'sort_key', 'category', 'slug'))
         if isinstance(objects, QuerySet):
             objects = prefetch_relations(objects, 'author')
@@ -169,8 +176,7 @@ def analyse_tags(request, tag_str):
         chunks = tag_str.split('/')
         if len(chunks) == 2 and chunks[0] == 'autor':
             raise ResponseInstead(pdcounter_views.author_detail(request, chunks[1]))
-        else:
-            raise Http404
+        raise Http404
     except Tag.MultipleObjectsReturned as e:
         # Ask the user to disambiguate
         raise ResponseInstead(differentiate_tags(request, e.tags, e.ambiguous_slugs))
@@ -243,7 +249,9 @@ def tagged_object_list(request, tags, list_type):
         params = {
             'objects': Book.tagged.with_all(tags, audiobooks),
             'extra': {
-                'daisy': Book.tagged.with_all(tags, audiobooks.filter(media__type='daisy').distinct()),
+                'daisy': Book.tagged.with_all(
+                    tags, audiobooks.filter(media__type='daisy').distinct()
+                ),
             }
         }
     else:
@@ -342,11 +350,13 @@ def import_book(request):
             exception = pprint.pformat(info[1])
             tb = '\n'.join(traceback.format_tb(info[2]))
             return HttpResponse(
-                    _("An error occurred: %(exception)s\n\n%(tb)s") % {'exception': exception, 'tb': tb},
-                    mimetype='text/plain')
+                _("An error occurred: %(exception)s\n\n%(tb)s") % {
+                    'exception': exception, 'tb': tb
+                },
+                mimetype='text/plain'
+            )
         return HttpResponse(_("Book imported successfully"))
-    else:
-        return HttpResponse(_("Error importing file: %r") % book_import_form.errors)
+    return HttpResponse(_("Error importing file: %r") % book_import_form.errors)
 
 
 # info views for API
@@ -405,7 +415,7 @@ class CustomPDFFormView(AjaxableFormView):
 
     def validate_object(self, obj, request):
         book = obj
-        if book.preview and not Membership_is_active_for(request.user):
+        if book.preview and not Membership.is_active_for(request.user):
             return HttpResponseRedirect(book.get_absolute_url())
         return super(CustomPDFFormView, self).validate_object(obj, request)
 
index a2dfbb9..7a3795a 100644 (file)
@@ -1,26 +1,26 @@
 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
-from django.conf.urls import url
+from django.urls import path
 from annoy.utils import banner_exempt
 from . import views
 
 
 urlpatterns = [
-    url(r'^$', banner_exempt(views.JoinView.as_view()), name='club_join'),
-    url(r'^info/$', banner_exempt(views.ClubView.as_view()), name='club'),
+    path('', banner_exempt(views.JoinView.as_view()), name='club_join'),
+    path('info/', banner_exempt(views.ClubView.as_view()), name='club'),
 
-    url(r'^plan/(?P<key>[-a-z0-9]+)/$', banner_exempt(views.ScheduleView.as_view()), name='club_schedule'),
-    url(r'^plan/(?P<key>[-a-z0-9]+)/dziekujemy/$', banner_exempt(views.ScheduleThanksView.as_view()), name='club_thanks'),
+    path('plan/<key>/', banner_exempt(views.ScheduleView.as_view()), name='club_schedule'),
+    path('plan/<key>/dziekujemy/', banner_exempt(views.ScheduleThanksView.as_view()), name='club_thanks'),
 
-    url(r'^przylacz/(?P<key>[-a-z0-9]+)/$', views.claim, name='club_claim'),
-    url(r'^anuluj/(?P<key>[-a-z0-9]+)/$', views.cancel, name='club_cancel'),
-    url(r'^testowa-platnosc/(?P<key>[-a-z0-9]+)/$', views.DummyPaymentView.as_view(), name='club_dummy_payment'),
+    path('przylacz/<key>/', views.claim, name='club_claim'),
+    path('anuluj/<key>/', views.cancel, name='club_cancel'),
+    path('testowa-platnosc/<key>/', views.DummyPaymentView.as_view(), name='club_dummy_payment'),
 
-    url(r'platnosc/payu/cykl/(?P<key>.+)/', banner_exempt(views.PayURecPayment.as_view()), name='club_payu_rec_payment'),
-    url(r'platnosc/payu/(?P<key>.+)/', banner_exempt(views.PayUPayment.as_view()), name='club_payu_payment'),
+    path('platnosc/payu/cykl/<key>/', banner_exempt(views.PayURecPayment.as_view()), name='club_payu_rec_payment'),
+    path('platnosc/payu/<key>/', banner_exempt(views.PayUPayment.as_view()), name='club_payu_payment'),
 
-    url(r'notify/(?P<pk>\d+)/', views.PayUNotifyView.as_view(), name='club_payu_notify'),
+    path('notify/<int:pk>/', views.PayUNotifyView.as_view(), name='club_payu_notify'),
 
-    url(r'czlonek/', views.MembershipView.as_view(), name='club_membership'),
+    path('czlonek/', views.MembershipView.as_view(), name='club_membership'),
 ]
index 2baf628..3ab98fc 100755 (executable)
@@ -1,9 +1,9 @@
 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
-from django.conf.urls import url
+from django.urls import path
 from dictionary.views import NotesView
 
 urlpatterns = [
-    url(r'^$', NotesView.as_view(), name='dictionary_notes'),
+    path('', NotesView.as_view(), name='dictionary_notes'),
 ]
index 986c4f0..3aae4ea 100644 (file)
@@ -1,22 +1,22 @@
 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
-from django.conf.urls import url, include
+from django.urls import path, include
 from . import views
 
 
 urlpatterns = [
-    url(r'^$', views.CurrentView.as_view(), name='funding_current'),
-    url(r'^teraz/$', views.CurrentView.as_view()),
-    url(r'^teraz/(?P<slug>[^/]+)/$', views.CurrentView.as_view(), name='funding_current'),
-    url(r'^lektura/$', views.OfferListView.as_view(), name='funding'),
-    url(r'^lektura/(?P<slug>[^/]+)/$', views.OfferDetailView.as_view(), name='funding_offer'),
-    url(r'^pozostale/$', views.WLFundView.as_view(), name='funding_wlfund'),
+    path('', views.CurrentView.as_view(), name='funding_current'),
+    path('teraz/', views.CurrentView.as_view()),
+    path('teraz/<slug:slug>/', views.CurrentView.as_view(), name='funding_current'),
+    path('lektura/', views.OfferListView.as_view(), name='funding'),
+    path('lektura/<slug:slug>/', views.OfferDetailView.as_view(), name='funding_offer'),
+    path('pozostale/', views.WLFundView.as_view(), name='funding_wlfund'),
 
-    url(r'^dziekujemy/$', views.ThanksView.as_view(), name='funding_thanks'),
-    url(r'^niepowodzenie/$', views.NoThanksView.as_view(), name='funding_nothanks'),
+    path('dziekujemy/', views.ThanksView.as_view(), name='funding_thanks'),
+    path('niepowodzenie/', views.NoThanksView.as_view(), name='funding_nothanks'),
 
-    url(r'^wylacz_email/$', views.DisableNotifications.as_view(), name='funding_disable_notifications'),
+    path('wylacz_email/', views.DisableNotifications.as_view(), name='funding_disable_notifications'),
 
-    url(r'^getpaid/', include('getpaid.urls')),
+    path('getpaid/', include('getpaid.urls')),
 ]
index 9d82335..233345a 100755 (executable)
@@ -1,10 +1,10 @@
 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
-from django.conf.urls import url
+from django.urls import path
 from . import views
 
 
 urlpatterns = [
-    url(r'^(?P<slug>[a-zA-Z0-9_-]+)/$', views.infopage, name='infopage'),
+    path('<slug>/', views.infopage, name='infopage'),
 ]
index 2a977e5..893831e 100644 (file)
@@ -1,15 +1,15 @@
 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
-from django.conf.urls import url
+from django.urls import path
 from . import views
 
 urlpatterns = (
-    url(r'^dodaj/$', views.add_isbn_wl, name='add_isbn_wl'),
-    url(r'^potwierdzenie/$', views.confirm_isbn_wl, name='confirm_isbn_wl'),
-    url(r'^save-wl-onix/$', views.save_wl_onix, name='save_wl_onix'),
-    url(r'^tagi-isbn/(?P<slug>[a-z0-9-]*)/$', views.wl_dc_tags, name='wl_dc_tags'),
+    path('dodaj/', views.add_isbn_wl, name='add_isbn_wl'),
+    path('potwierdzenie/', views.confirm_isbn_wl, name='confirm_isbn_wl'),
+    path('save-wl-onix/', views.save_wl_onix, name='save_wl_onix'),
+    path('tagi-isbn/<slug:slug>/', views.wl_dc_tags, name='wl_dc_tags'),
 
-    url(r'^dodaj-fnp/$', views.add_isbn_fnp, name='add_isbn_fnp'),
-    url(r'^przypisane/(?P<slug>[a-z0-9-]*)/$', views.assigned_isbn, name='assigned_isbn'),
+    path('dodaj-fnp/', views.add_isbn_fnp, name='add_isbn_fnp'),
+    path('przypisane/<slug:slug>/', views.assigned_isbn, name='assigned_isbn'),
 )
index 15d6f25..dbee5f8 100644 (file)
@@ -1,14 +1,14 @@
 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
-from django.conf.urls import url
+from django.urls import path
 from . import views
 
 
 urlpatterns = [
-    url(r'^$', views.main_page, name='lesmianator'),
-    url(r'^wiersz/$', views.new_poem, name='new_poem'),
-    url(r'^lektura/(?P<slug>[a-z0-9-]+)/$', views.poem_from_book, name='poem_from_book'),
-    url(r'^polka/(?P<shelf>[a-zA-Z0-9-]+)/$', views.poem_from_set, name='poem_from_set'),
-    url(r'^wiersz/(?P<poem>[a-zA-Z0-9-]+)/$', views.get_poem, name='get_poem'),
+    path('', views.main_page, name='lesmianator'),
+    path('wiersz/', views.new_poem, name='new_poem'),
+    path('lektura/<slug:slug>/', views.poem_from_book, name='poem_from_book'),
+    path('polka/<shelf>/', views.poem_from_set, name='poem_from_set'),
+    path('wiersz/<poem>/', views.get_poem, name='get_poem'),
 ]
index 3e3d78e..9753b77 100644 (file)
@@ -1,12 +1,12 @@
 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
-from django.conf.urls import url
+from django.urls import path
 from . import views
 
 
 urlpatterns = [
-    url(r'^$', views.main_view, name='libraries_main_view'),
-    url(r'^(?P<slug>[a-zA-Z0-9_-]+)$', views.catalog_view, name='libraries_catalog_view'),
-    url(r'^(?P<catalog_slug>[a-zA-Z0-9_-]+)/(?P<slug>[a-zA-Z0-9_-]+)$', views.library_view, name='libraries_library_view'),
+    path('', views.main_view, name='libraries_main_view'),
+    path('<slug:slug>', views.catalog_view, name='libraries_catalog_view'),
+    path('<slug:catalog_slug>/<slug:slug>', views.library_view, name='libraries_library_view'),
 ]
index 530eeca..48134b1 100644 (file)
@@ -1,7 +1,7 @@
 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
-from django.conf.urls import url
+from django.urls import path
 from django.contrib import admin
 from django.http.response import HttpResponse
 from django.views.decorators.cache import never_cache
@@ -16,7 +16,7 @@ class SubscriptionAdmin(admin.ModelAdmin):
     def get_urls(self):
         urls = super(SubscriptionAdmin, self).get_urls()
         my_urls = [
-            url(r'^extract/$', self.extract_subscribers, name='extract_subscribers'),
+            path('extract/', self.extract_subscribers, name='extract_subscribers'),
         ]
         return my_urls + urls
 
index c99b47a..bfae579 100644 (file)
@@ -1,14 +1,14 @@
 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
-from django.conf.urls import url
+from django.urls import path
 from . import views
 
 urlpatterns = [
-    url(r'^zapisz-sie/$', views.subscribe_form, name='subscribe'),
-    url(r'^zapis/$', views.subscribed, name='subscribed'),
-    url(r'^potwierdzenie/(?P<subscription_id>[0-9]+)/(?P<hashcode>[0-9a-f]+)/$',
+    path('zapisz-sie/', views.subscribe_form, name='subscribe'),
+    path('zapis/', views.subscribed, name='subscribed'),
+    path('potwierdzenie/<int:subscription_id>/<slug:hashcode>/',
         views.confirm_subscription, name='confirm_subscription'),
-    url(r'^wypisz-sie/$', views.unsubscribe_form, name='unsubscribe'),
-    url(r'^wypisano/$', views.unsubscribed, name='unsubscribed'),
+    path('wypisz-sie/', views.unsubscribe_form, name='unsubscribe'),
+    path('wypisano/', views.unsubscribed, name='unsubscribed'),
 ]
index 2088a8a..85c31af 100644 (file)
@@ -1,10 +1,10 @@
 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
-from django.conf.urls import url
+from django.urls import path
 from . import views
 
 
 urlpatterns = [
-    url(r'^$', views.oaipmh, name='oaipmh')
+    path('', views.oaipmh, name='oaipmh')
 ]
index 213c55a..1d68199 100644 (file)
@@ -1,15 +1,15 @@
 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
-from django.conf.urls import url
+from django.urls import path
 from opds.views import RootFeed, ByCategoryFeed, ByTagFeed, UserFeed, UserSetFeed, SearchFeed
 
 
 urlpatterns = [
-    url(r'^$', RootFeed(), name="opds_authors"),
-    url(r'^search/$', SearchFeed(), name="opds_search"),
-    url(r'^user/$', UserFeed(), name="opds_user"),
-    url(r'^set/(?P<slug>[a-zA-Z0-9-]+)/$', UserSetFeed(), name="opds_user_set"),
-    url(r'^(?P<category>[a-zA-Z0-9-]+)/$', ByCategoryFeed(), name="opds_by_category"),
-    url(r'^(?P<category>[a-zA-Z0-9-]+)/(?P<slug>[a-zA-Z0-9-]+)/$', ByTagFeed(), name="opds_by_tag"),
+    path('', RootFeed(), name="opds_authors"),
+    path('search/', SearchFeed(), name="opds_search"),
+    path('user/', UserFeed(), name="opds_user"),
+    path('set/<slug>/', UserSetFeed(), name="opds_user_set"),
+    path('<category>/', ByCategoryFeed(), name="opds_by_category"),
+    path('<category>/<slug>/', ByTagFeed(), name="opds_by_tag"),
 ]
index bd26993..aca8918 100644 (file)
@@ -1,15 +1,15 @@
 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
-from django.conf.urls import url
+from django.urls import path
 from django.views.generic import RedirectView
 from . import views
 
 urlpatterns = (
-    url(r'^form/$', RedirectView.as_view(url='/towarzystwo/dolacz/')),
-    url(r'^app-form/$', RedirectView.as_view(url='/towarzystwo/dolacz/app/')),
+    path('form/', RedirectView.as_view(url='/towarzystwo/dolacz/')),
+    path('app-form/', RedirectView.as_view(url='/towarzystwo/dolacz/app/')),
 
-    url(r'^return/$', views.paypal_return, name='paypal_return'),
-    url(r'^app-return/$', views.paypal_return, kwargs={'app': True}, name='paypal_app_return'),
-    url(r'^cancel/$', views.paypal_cancel, name='paypal_cancel'),
+    path('return/', views.paypal_return, name='paypal_return'),
+    path('app-return/', views.paypal_return, kwargs={'app': True}, name='paypal_app_return'),
+    path('cancel/', views.paypal_cancel, name='paypal_cancel'),
 )
index cb457f5..95fd103 100644 (file)
@@ -1,10 +1,10 @@
 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
-from django.conf.urls import url
+from django.urls import path
 from . import views
 
 
 urlpatterns = [
-    url(r'^$', views.PicturesView.as_view()),
+    path('', views.PicturesView.as_view()),
 ]
index 897686b..f2d3a02 100644 (file)
@@ -1,10 +1,10 @@
 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
-from django.conf.urls import url
+from django.urls import path
 from . import views
 
 
 urlpatterns = [
-    url(r'^(?P<slug>[^/]+)$', views.poll, name='poll'),
+    path('<slug:slug>', views.poll, name='poll'),
 ]
index c7f64d9..a92a55f 100644 (file)
@@ -1,11 +1,11 @@
 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
-from django.conf.urls import url
+from django.urls import path
 from push import views
 
 
 urlpatterns = [
-    url(r'^wyslij/$', views.notification_form, name='notification_form'),
-    url(r'^wyslane/$', views.notification_sent, name='notification_sent'),
+    path('wyslij/', views.notification_form, name='notification_form'),
+    path('wyslane/', views.notification_sent, name='notification_sent'),
 ]
index fa7ceb2..a9ae44a 100755 (executable)
@@ -1,12 +1,12 @@
 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
-from django.conf.urls import url
+from django.urls import path
 from . import views
 
 
 urlpatterns = [
-    url(r'^$', views.stats_page, name='reporting_stats'),
-    url(r'^katalog.pdf$', views.catalogue_pdf, name='reporting_catalogue_pdf'),
-    url(r'^katalog.csv$', views.catalogue_csv, name='reporting_catalogue_csv'),
+    path('', views.stats_page, name='reporting_stats'),
+    path('katalog.pdf', views.catalogue_pdf, name='reporting_catalogue_pdf'),
+    path('katalog.csv', views.catalogue_csv, name='reporting_catalogue_csv'),
 ]
index 980f5e8..46e73c5 100644 (file)
@@ -1,11 +1,11 @@
 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
-from django.conf.urls import url
+from django.urls import path
 from . import views
 
 
 urlpatterns = [
-    url(r'^$', views.main, name='wlsearch'),
-    url(r'^hint/$', views.hint, name='search_hint'),
+    path('', views.main, name='wlsearch'),
+    path('hint/', views.hint, name='search_hint'),
 ]
index 2ed2d66..2b20ab8 100644 (file)
@@ -1,16 +1,16 @@
 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
-from django.conf.urls import include, url
+from django.urls import path
 from stats.utils import piwik_track_view
 from . import views
 
 
 urlpatterns = [
-    url(r'^like/(?P<slug>[a-z0-9-]+)/$',
+    path('like/<slug:slug>/',
         piwik_track_view(views.LikeView.as_view()),
         name='social_api_like'),
-    url(r'^shelf/(?P<state>[a-z]+)/$',
+    path('shelf/<slug:state>/',
         piwik_track_view(views.ShelfView.as_view()),
         name='social_api_shelf'),
 ]
index 6b78950..e092ff0 100644 (file)
@@ -1,14 +1,14 @@
 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
-from django.conf.urls import url
+from django.urls import path
 from django.views.decorators.cache import never_cache
 from . import views
 
 
 urlpatterns = [
-    url(r'^lektura/(?P<slug>[a-z0-9-]+)/lubie/$', views.like_book, name='social_like_book'),
-    url(r'^lektura/(?P<slug>[a-z0-9-]+)/nie_lubie/$', views.unlike_book, name='social_unlike_book'),
-    url(r'^lektura/(?P<slug>[a-z0-9-]+)/polki/$', never_cache(views.ObjectSetsFormView()), name='social_book_sets'),
-    url(r'^polka/$', views.my_shelf, name='social_my_shelf'),
+    path('lektura/<slug:slug>/lubie/', views.like_book, name='social_like_book'),
+    path('lektura/<slug:slug>/nie_lubie/', views.unlike_book, name='social_unlike_book'),
+    path('lektura/<slug:slug>/polki/', never_cache(views.ObjectSetsFormView()), name='social_book_sets'),
+    path('polka/', views.my_shelf, name='social_my_shelf'),
 ]
index 4a03a0d..7f15ac5 100644 (file)
@@ -1,10 +1,10 @@
 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
-from django.conf.urls import url
+from django.urls import path
 from suggest import views
 
 urlpatterns = [
-    url(r'^$', views.SuggestionFormView(), name='suggest'),
-    url(r'^plan/$', views.PublishingSuggestionFormView(), name='suggest_publishing'),
+    path('', views.SuggestionFormView(), name='suggest'),
+    path('plan/', views.PublishingSuggestionFormView(), name='suggest_publishing'),
 ]
index ffe9805..1c8b17f 100644 (file)
@@ -1,9 +1,9 @@
 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
-from django.conf.urls import url
+from django.urls import path
 from waiter import views
 
 urlpatterns = [
-    url(r'^(?P<path>.*)$', views.wait, name='waiter'),
+    path('<path:path>', views.wait, name='waiter'),
 ]
index 43b6d95..b215081 100644 (file)
@@ -2,7 +2,7 @@
 {% spaceless %}
   <html lang="{{ LANGUAGE_CODE }}" prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb#">
     {% load pipeline i18n %}
-    {% load static from staticfiles %}
+    {% load static %}
     {% load piwik_tags %}
     {% get_current_language as LANGUAGE_CODE %}
     <head>
index bd7de37..cdbdb69 100644 (file)
@@ -2,7 +2,7 @@
 {% spaceless %}
   <html lang="{{ LANGUAGE_CODE }}" prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb#">
     {% load pipeline i18n %}
-    {% load static from staticfiles %}
+    {% load static %}
     {% load catalogue_tags funding_tags reporting_stats %}
     {% load piwik_tags %}
     {% load cache %}
index 71731b9..9d5b1fb 100644 (file)
@@ -1,7 +1,7 @@
 {% extends "base/base.html" %}
 {% load latest_blog_posts from blog %}
 {% load carousel from social_tags %}
-{% load static from staticfiles %}
+{% load static %}
 {% load i18n catalogue_tags infopages_tags %}
 {% load cache %}
 {% load funding_tags %}
index de79b56..3eb3422 100644 (file)
@@ -1,5 +1,5 @@
 {% spaceless %}
-  {% load static from staticfiles %}
+  {% load static %}
   {% load pipeline %}
   <!DOCTYPE html>
 
index c328c83..af6244c 100644 (file)
@@ -1,9 +1,9 @@
 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
-from django.conf.urls import include, url
 from django.conf import settings
 from django.contrib import admin
+from django.urls import include, path
 from django.views.generic import RedirectView
 import django.views.static
 import catalogue.views
@@ -12,100 +12,97 @@ from . import views
 
 
 urlpatterns = [
-    url(r'^$', views.main_page, name='main_page'),
-    url(r'^planowane/$', views.publish_plan, name='publish_plan'),
-    url(r'^widget\.html$', views.widget, name='widget'),
+    path('', views.main_page, name='main_page'),
+    path('planowane/', views.publish_plan, name='publish_plan'),
+    path('widget.html', views.widget, name='widget'),
 
-    url(r'^zegar/$', views.clock, name='clock'),
+    path('zegar/', views.clock, name='clock'),
 
     # Authentication
-    url(r'^uzytkownik/$', views.user_settings, name='user_settings'),
-    url(r'^uzytkownik/login/$', views.LoginFormView(), name='login'),
-    url(r'^uzytkownik/signup/$', views.RegisterFormView(), name='register'),
-    url(r'^uzytkownik/logout/$', views.logout_then_redirect, name='logout'),
-    url(r'^uzytkownik/zaloguj-utworz/$', views.LoginRegisterFormView(), name='login_register'),
-    url(r'^uzytkownik/social/signup/$', views.SocialSignupView.as_view(), name='socialaccount_signup'),
+    path('uzytkownik/', views.user_settings, name='user_settings'),
+    path('uzytkownik/login/', views.LoginFormView(), name='login'),
+    path('uzytkownik/signup/', views.RegisterFormView(), name='register'),
+    path('uzytkownik/logout/', views.logout_then_redirect, name='logout'),
+    path('uzytkownik/zaloguj-utworz/', views.LoginRegisterFormView(), name='login_register'),
+    path('uzytkownik/social/signup/', views.SocialSignupView.as_view(), name='socialaccount_signup'),
 ]
 
 urlpatterns += [
-    url(r'^katalog/', include('catalogue.urls')),
-    url(r'^opds/', include('opds.urls')),
-    url(r'^sugestia/', include('suggest.urls')),
-    url(r'^lesmianator/', include('lesmianator.urls')),
-    url(r'^przypisy/', include('dictionary.urls')),
-    url(r'^raporty/', include('reporting.urls')),
-    url(r'^info/', include('infopages.urls')),
-    url(r'^ludzie/', include('social.urls')),
-    url(r'^uzytkownik/', include('allauth.urls')),
-    url(r'^czekaj/', include('waiter.urls')),
-    url(r'^wesprzyj/', include('funding.urls')),
-    url(r'^ankieta/', include('polls.urls')),
-    url(r'^biblioteki/', include('libraries.urls')),
-    url(r'^newsletter/', include('newsletter.urls')),
-    url(r'^formularz/', include('forms_builder.forms.urls')),
-    url(r'^isbn/', include('isbn.urls')),
-    url(r'^messaging/', include('messaging.urls')),
-
-    url(r'^paypal/app-form/$', RedirectView.as_view(
+    path('katalog/', include('catalogue.urls')),
+    path('opds/', include('opds.urls')),
+    path('sugestia/', include('suggest.urls')),
+    path('lesmianator/', include('lesmianator.urls')),
+    path('przypisy/', include('dictionary.urls')),
+    path('raporty/', include('reporting.urls')),
+    path('info/', include('infopages.urls')),
+    path('ludzie/', include('social.urls')),
+    path('uzytkownik/', include('allauth.urls')),
+    path('czekaj/', include('waiter.urls')),
+    path('wesprzyj/', include('funding.urls')),
+    path('ankieta/', include('polls.urls')),
+    path('biblioteki/', include('libraries.urls')),
+    path('newsletter/', include('newsletter.urls')),
+    path('formularz/', include('forms_builder.forms.urls')),
+    path('isbn/', include('isbn.urls')),
+    path('messaging/', include('messaging.urls')),
+
+    path('paypal/app-form/', RedirectView.as_view(
         url='/towarzystwo/?app=1', permanent=False)),
-    url(r'^towarzystwo/dolacz/$', RedirectView.as_view(
+    path('towarzystwo/dolacz/', RedirectView.as_view(
         url='/towarzystwo/', permanent=False)),
 
-
-    url(r'^paypal/', include('paypal.urls')),
-    url(r'^powiadomienie/', include('push.urls')),
-    url(r'^towarzystwo/', include('club.urls')),
+    path('paypal/', include('paypal.urls')),
+    path('powiadomienie/', include('push.urls')),
+    path('towarzystwo/', include('club.urls')),
 
     # Admin panel
-    url(r'^admin/catalogue/book/import$', catalogue.views.import_book, name='import_book'),
-    url(r'^admin/catalogue/picture/import$', picture.views.import_picture, name='import_picture'),
-    url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
-    url(r'^admin/', admin.site.urls),
+    path('admin/catalogue/book/import', catalogue.views.import_book, name='import_book'),
+    path('admin/catalogue/picture/import', picture.views.import_picture, name='import_picture'),
+    path('admin/doc/', include('django.contrib.admindocs.urls')),
+    path('admin/', admin.site.urls),
 
     # API
-    url(r'^api/', include('api.urls')),
+    path('api/', include('api.urls')),
     # OAIPMH
-    url(r'^oaipmh/', include('oai.urls')),
+    path('oaipmh/', include('oai.urls')),
 
-    url(r'^szukaj/', include('search.urls')),
+    path('szukaj/', include('search.urls')),
 
-    url(r'^i18n/', include('django.conf.urls.i18n')),
-    url(r'^forum/', include('machina.urls')),
+    path('i18n/', include('django.conf.urls.i18n')),
+    path('forum/', include('machina.urls')),
 ]
 
 urlpatterns += [
     # old static pages - redirected
-    url(r'^1procent/$', RedirectView.as_view(
+    path('1procent/', RedirectView.as_view(
         url='http://nowoczesnapolska.org.pl/wesprzyj_nas/', permanent=True)),
-    url(r'^epub/$', RedirectView.as_view(
+    path('epub/', RedirectView.as_view(
         url='/katalog/lektury/', permanent=False)),
-    url(r'^mozesz-nam-pomoc/$', RedirectView.as_view(
+    path('mozesz-nam-pomoc/', RedirectView.as_view(
         url='/info/wlacz-sie-w-prace/', permanent=True)),
-    url(r'^o-projekcie/$', RedirectView.as_view(
+    path('o-projekcie/', RedirectView.as_view(
         url='/info/o-projekcie/', permanent=True)),
-    url(r'^widget/$', RedirectView.as_view(
+    path('widget/', RedirectView.as_view(
         url='/info/widget/', permanent=True)),
-    url(r'^wolontariat/$', RedirectView.as_view(
+    path('wolontariat/', RedirectView.as_view(
         url='/info/wlacz-sie-w-prace/', permanent=False)),
 ]
 
 urlpatterns += [
-    url(r'^error-test/$', views.exception_test),
-    # url(r'^post-test/$', views.post_test),
+    # path('error-test/', views.exception_test),
+    # path('post-test/', views.post_test),
 ]
 
 
 if settings.DEBUG:
     import debug_toolbar
     urlpatterns = [
-        url(r'^__debug__/', include(debug_toolbar.urls)),
+        path('__debug__/', include(debug_toolbar.urls)),
     ] + urlpatterns
 
 if settings.DEBUG:
     urlpatterns += [
         # Static files
-        url(r'^%s(?P<path>.*)$' % settings.MEDIA_URL[1:], django.views.static.serve,
+        path('%s<path:path>' % settings.MEDIA_URL[1:], django.views.static.serve,
            {'document_root': settings.MEDIA_ROOT, 'show_indexes': True}),
-        url(r'^%s(?P<path>.*)$' % settings.STATIC_URL[1:], django.views.static.serve,
-            {'document_root': settings.STATIC_ROOT, 'show_indexes': True}),
     ]