diff --git a/lib/booki/editor/management/commands/brokenlinks.py b/lib/booki/editor/management/commands/brokenlinks.py
index 94ea738a0..4801889eb 100644
--- a/lib/booki/editor/management/commands/brokenlinks.py
+++ b/lib/booki/editor/management/commands/brokenlinks.py
@@ -15,7 +15,7 @@
# along with Booktype. If not, see .
import os
-import urllib2
+from urllib import request as urllib2
from lxml import etree, html
from django.test import Client
@@ -40,14 +40,14 @@ def checkLink(options, chapter, urlLink):
if urlLink.startswith(hostUrl):
return
- print ' >>> ', urlLink,
+ print(' >>> ', urlLink,)
if cacheLinks.get(urlLink):
returnCode = cacheLinks.get(urlLink)
else:
try:
response = urllib2.urlopen(HeadRequest(urlLink))
- except IOError, e:
+ except IOError as e:
if hasattr(e, 'reason'):
returnCode = e.reason
elif hasattr(e, 'code'):
@@ -58,7 +58,7 @@ def checkLink(options, chapter, urlLink):
if not options['no_cache']:
cacheLinks[urlLink] = returnCode
- print ' [%s]' % returnCode
+ print(' [%s]' % returnCode)
else:
if options['no_local']: return
@@ -66,10 +66,10 @@ def checkLink(options, chapter, urlLink):
newUrl = os.path.normpath('/%s/_v/%s/%s/%s' % (
chapter.version.book.url_title, chapter.version.getVersion(), chapter.url_title, urlLink))
- print ' >> ', newUrl,
+ print(' >> ', newUrl,)
response = c.get(newUrl)
- print ' [%s]' % response.status_code
+ print(' [%s]' % response.status_code)
class Command(BaseCommand):
@@ -115,17 +115,17 @@ def handle(self, *args, **options):
booksList = models.Book.objects.all().order_by('url_title')
for book in booksList:
- print '[%s]' % book.url_title
+ print('[%s]' % book.url_title)
try:
for chapter in models.Chapter.objects.filter(version__book=book):
- print ' [%s]' % chapter.url_title,
+ print(' [%s]' % chapter.url_title,)
try:
tree = html.document_fromstring(chapter.content)
- print ''
+ print('')
except:
- print ' [ERROR PARSING HTML]'
+ print(' [ERROR PARSING HTML]')
continue
for elem in tree.iter():
diff --git a/lib/booki/editor/management/commands/confdel.py b/lib/booki/editor/management/commands/confdel.py
index 8c4c43197..6d874ce38 100644
--- a/lib/booki/editor/management/commands/confdel.py
+++ b/lib/booki/editor/management/commands/confdel.py
@@ -34,7 +34,7 @@ def handle(self, *args, **options):
if not options[''][0]:
raise CommandError("You must specify variable name")
- if not settings.BOOKTYPE_CONFIG.has_key(options[''][0]):
+ if options[''][0] not in settings.BOOKTYPE_CONFIG:
raise CommandError("There is no such variable.")
del settings.BOOKTYPE_CONFIG[options[''][0]]
diff --git a/lib/booki/editor/management/commands/confget.py b/lib/booki/editor/management/commands/confget.py
index ec34f8279..9c4f5f250 100644
--- a/lib/booki/editor/management/commands/confget.py
+++ b/lib/booki/editor/management/commands/confget.py
@@ -39,7 +39,7 @@ def handle(self, *args, **options):
if not options[""][0]:
raise CommandError("You must specify variable name")
- if not settings.BOOKTYPE_CONFIG.has_key(options[""][0]):
+ if options[""][0] not in settings.BOOKTYPE_CONFIG:
raise CommandError("There is no such variable.")
value = settings.BOOKTYPE_CONFIG[options[""][0]]
diff --git a/lib/booki/editor/management/commands/conflist.py b/lib/booki/editor/management/commands/conflist.py
index fa1a99845..b36c1eb33 100644
--- a/lib/booki/editor/management/commands/conflist.py
+++ b/lib/booki/editor/management/commands/conflist.py
@@ -35,7 +35,7 @@ def handle(self, *args, **options):
self.stderr.write('Does not have BOOKTYPE_CONFIG in settings.py file.')
return False
- for name in settings.BOOKTYPE_CONFIG.iterkeys():
+ for name in settings.BOOKTYPE_CONFIG.keys():
s = name
if options['values']:
diff --git a/lib/booki/editor/migrations/0002_load_initial_data.py b/lib/booki/editor/migrations/0002_load_initial_data.py
index 4eb852c4b..0975fb7dd 100644
--- a/lib/booki/editor/migrations/0002_load_initial_data.py
+++ b/lib/booki/editor/migrations/0002_load_initial_data.py
@@ -37,9 +37,9 @@ def load_data(apps, schema_editor):
license = License.objects.get(pk=data['pk'])
license.url = data['url']
license.save()
- print "Updating url '%s' to license '%s'" % (data['url'], license.name)
+ print("Updating url '%s' to license '%s'" % (data['url'], license.name))
except License.DoesNotExist:
- print "License with pk %s does not exist. Doing nothing" % data['pk']
+ print("License with pk %s does not exist. Doing nothing" % data['pk'])
class Migration(migrations.Migration):
diff --git a/lib/booki/editor/migrations/0004_convert_endnotes.py b/lib/booki/editor/migrations/0004_convert_endnotes.py
index fe0b84c36..a8bc3e8b0 100644
--- a/lib/booki/editor/migrations/0004_convert_endnotes.py
+++ b/lib/booki/editor/migrations/0004_convert_endnotes.py
@@ -19,7 +19,7 @@ def convert_endnotes(apps, schema_editor):
# converting
tree, _ = EpubImporter.convert_endnotes(tree)
- content = unicode(etree.tostring(tree, pretty_print=True, encoding='utf-8',
+ content = str(etree.tostring(tree, pretty_print=True, encoding='utf-8',
xml_declaration=False), 'utf-8')
# remove redundant div wrapper
diff --git a/lib/booki/editor/models.py b/lib/booki/editor/models.py
index ccc893564..1cc9cf5c4 100644
--- a/lib/booki/editor/models.py
+++ b/lib/booki/editor/models.py
@@ -39,7 +39,7 @@ class License(models.Model):
abbrevation = models.CharField(_('abbreviation'), max_length=30)
url = models.URLField(_('url'), blank=True, null=True)
- def __unicode__(self):
+ def __str__(self):
return self.name
class Meta:
@@ -53,7 +53,7 @@ class Language(models.Model):
abbrevation = models.CharField(_('abbreviation'),
max_length=10, blank=False)
- def __unicode__(self):
+ def __str__(self):
return self.name
class Meta:
@@ -70,12 +70,12 @@ class Meta:
class BookStatus(models.Model):
- book = models.ForeignKey('Book', verbose_name=_("book"))
+ book = models.ForeignKey('Book', on_delete=models.CASCADE, verbose_name=_("book"))
name = models.CharField(_('name'), max_length=30, blank=False)
weight = models.SmallIntegerField(_('weight'))
color = models.CharField(_('color'), max_length=30, default='', blank=True)
- def __unicode__(self):
+ def __str__(self):
return self.name
class Meta:
@@ -86,10 +86,10 @@ class Meta:
# free form shared notes for writers of the book
class BookNotes(models.Model):
- book = models.ForeignKey('Book', verbose_name=_("book"))
+ book = models.ForeignKey('Book', on_delete=models.CASCADE, verbose_name=_("book"))
notes = models.TextField(_('notes'))
- def __unicode__(self):
+ def __str__(self):
return u"Notes for " + self.book.title
class Meta:
@@ -102,7 +102,7 @@ class BookiGroup(models.Model):
url_name = models.CharField(_('url name'), max_length=300, blank=False)
description = models.TextField(_('description'))
- owner = models.ForeignKey(auth_models.User, verbose_name=_('owner'))
+ owner = models.ForeignKey(auth_models.User, on_delete=models.CASCADE, verbose_name=_('owner'))
members = models.ManyToManyField(auth_models.User, related_name="members",
blank=True, verbose_name=_("members"))
@@ -144,7 +144,7 @@ def remove_group_images(self):
except Exception as e:
logger.exception(e)
- def __unicode__(self):
+ def __str__(self):
return self.name
class Meta:
@@ -185,16 +185,16 @@ class Meta:
class Book(models.Model):
url_title = models.CharField(_('url title'), max_length=2500, blank=False, unique=True) # can it be blank?
title = models.CharField(_('title'), max_length=2500, blank=False)
- status = models.ForeignKey('BookStatus', null=True, related_name="status", verbose_name=_("status"))
- language = models.ForeignKey(Language, null=True, verbose_name=_("language")) # can it be blank?
+ status = models.ForeignKey('BookStatus', on_delete=models.CASCADE, null=True, related_name="status", verbose_name=_("status"))
+ language = models.ForeignKey(Language, on_delete=models.CASCADE, null=True, verbose_name=_("language")) # can it be blank?
- version = models.ForeignKey('BookVersion', null=True, related_name="version", verbose_name=_("version"))
+ version = models.ForeignKey('BookVersion', on_delete=models.CASCADE, null=True, related_name="version", verbose_name=_("version"))
- group = models.ForeignKey(BookiGroup, null=True, verbose_name=_("group"))
+ group = models.ForeignKey(BookiGroup, on_delete=models.CASCADE, null=True, verbose_name=_("group"))
- owner = models.ForeignKey(auth_models.User, verbose_name=_("owner"))
+ owner = models.ForeignKey(auth_models.User, on_delete=models.CASCADE, verbose_name=_("owner"))
- license = models.ForeignKey(License, null=True, blank=True, verbose_name=_("license"))
+ license = models.ForeignKey(License, on_delete=models.CASCADE, null=True, blank=True, verbose_name=_("license"))
created = models.DateTimeField(_('created'), auto_now=False, default=datetime.datetime.now)
published = models.DateTimeField(_('published'), null=True)
@@ -209,7 +209,7 @@ class Meta:
verbose_name = _('Book')
verbose_name_plural = _('Books')
- def __unicode__(self):
+ def __str__(self):
return self.title
def get_absolute_url(self):
@@ -330,17 +330,17 @@ def author(self, name):
class BookHistory(models.Model):
- book = models.ForeignKey(Book, null=False, verbose_name=_("book"))
+ book = models.ForeignKey(Book, on_delete=models.CASCADE, null=False, verbose_name=_("book"))
# this should probably be null=False
- version = models.ForeignKey('BookVersion', null=True, verbose_name=_("version"))
- chapter = models.ForeignKey('Chapter', null=True, verbose_name=_("chapter"))
- chapter_history = models.ForeignKey('ChapterHistory', null=True, verbose_name=_("chapter history"))
+ version = models.ForeignKey('BookVersion', on_delete=models.CASCADE, null=True, verbose_name=_("version"))
+ chapter = models.ForeignKey('Chapter', on_delete=models.CASCADE, null=True, verbose_name=_("chapter"))
+ chapter_history = models.ForeignKey('ChapterHistory', on_delete=models.CASCADE, null=True, verbose_name=_("chapter history"))
modified = models.DateTimeField(_('modified'), auto_now=True)
args = models.CharField(_('args'), max_length=2500, blank=False)
- user = models.ForeignKey(auth_models.User, verbose_name=_("user"))
+ user = models.ForeignKey(auth_models.User, on_delete=models.CASCADE, verbose_name=_("user"))
kind = models.SmallIntegerField(_('kind'), default=0)
- def __unicode__(self):
+ def __str__(self):
return self.args
@@ -363,7 +363,7 @@ class BaseInfo(models.Model):
value_text = models.TextField(_('value text'), null=True)
value_date = models.DateTimeField(_('value date'), auto_now=False, null=True)
- def __unicode__(self):
+ def __str__(self):
return self.name
class Meta:
@@ -418,7 +418,7 @@ class Meta:
# Book Version
class BookVersion(models.Model):
- book = models.ForeignKey(Book, null=False, verbose_name=_("book"))
+ book = models.ForeignKey(Book, on_delete=models.CASCADE, null=False, verbose_name=_("book"))
major = models.IntegerField(_('major'))
minor = models.IntegerField(_('minor'))
name = models.CharField(_('name'), max_length=50, blank=True)
@@ -454,7 +454,7 @@ def get_version(self):
def get_absolute_url(self):
return '%s/%s/_v/%s/' % (settings.BOOKI_URL, self.book.url_title, self.get_version())
- def __unicode__(self):
+ def __str__(self):
return u'%d.%d (%s)' % (self.major, self.minor, self.name)
# DEPRECATED API NAMES
@@ -468,11 +468,11 @@ def __unicode__(self):
class Chapter(models.Model):
EDIT_PING_SECONDS_MAX_DELTA = 15
- version = models.ForeignKey(BookVersion, null=False, verbose_name=_('version'))
- book = models.ForeignKey(Book, null=False, verbose_name=_('book'))
+ version = models.ForeignKey(BookVersion, on_delete=models.CASCADE, null=False, verbose_name=_('version'))
+ book = models.ForeignKey(Book, on_delete=models.CASCADE, null=False, verbose_name=_('book'))
url_title = models.CharField(_('url title'), max_length=2500)
title = models.CharField(_('title'), max_length=2500)
- status = models.ForeignKey(BookStatus, null=False, verbose_name=_('status'))
+ status = models.ForeignKey(BookStatus, on_delete=models.CASCADE, null=False, verbose_name=_('status'))
# used to save statuses as checked
checked_statuses = models.ManyToManyField(
@@ -493,7 +493,7 @@ class Meta:
def get_absolute_url(self):
return '%s/%s/%s/' % (settings.BOOKI_URL, self.book.url_title, self.url_title)
- def __unicode__(self):
+ def __str__(self):
return self.title
@property
@@ -596,14 +596,14 @@ def has_marker(self):
class ChapterHistory(models.Model):
- chapter = models.ForeignKey(Chapter, null=False, verbose_name=_("chapter"))
+ chapter = models.ForeignKey(Chapter, on_delete=models.CASCADE, null=False, verbose_name=_("chapter"))
content = models.TextField()
modified = models.DateTimeField(_('modified'), null=False, auto_now=True)
- user = models.ForeignKey(auth_models.User, verbose_name=_("user"))
+ user = models.ForeignKey(auth_models.User, on_delete=models.CASCADE, verbose_name=_("user"))
revision = models.IntegerField(_('revision'), default=1)
comment = models.CharField(_('comment'), max_length=2500, blank=True)
- def __unicode__(self):
+ def __str__(self):
return u'{0} | {1} - {2}. Comment: {3}'.format(
self.chapter.book, self.chapter, self.modified, self.comment)
@@ -639,7 +639,7 @@ class ChapterLock(models.Model):
)
chapter = models.OneToOneField(Chapter, related_name='lock')
- user = models.ForeignKey(auth_models.User, verbose_name=_('user'))
+ user = models.ForeignKey(auth_models.User, on_delete=models.CASCADE, verbose_name=_('user'))
type = models.IntegerField(choices=LOCK_CHOICES, default=LOCK_SIMPLE)
created = models.DateTimeField(_('created'), auto_now_add=True)
@@ -648,7 +648,7 @@ class Meta:
verbose_name_plural = _('Chapters Locks')
ordering = ('created',)
- def __unicode__(self):
+ def __str__(self):
return u"{0} - {1}".format(self.chapter.title, self.get_type_display())
@@ -675,10 +675,10 @@ def get_directory_name(self):
class Attachment(models.Model):
- version = models.ForeignKey(BookVersion, null=False, verbose_name=_("version"))
- book = models.ForeignKey(Book, null=False, verbose_name=_("book"))
+ version = models.ForeignKey(BookVersion, on_delete=models.CASCADE, null=False, verbose_name=_("version"))
+ book = models.ForeignKey(Book, on_delete=models.CASCADE, null=False, verbose_name=_("book"))
attachment = models.FileField(_('filename'), upload_to=upload_attachment_to, max_length=2500)
- status = models.ForeignKey(BookStatus, null=False, verbose_name=_("status"))
+ status = models.ForeignKey(BookStatus, on_delete=models.CASCADE, null=False, verbose_name=_("status"))
created = models.DateTimeField(_('created'), null=False, auto_now=False, default=datetime.datetime.now)
def delete(self):
@@ -687,7 +687,7 @@ def delete(self):
super(Attachment, self).delete()
- def __unicode__(self):
+ def __str__(self):
return self.attachment.name
class Meta:
@@ -756,12 +756,12 @@ class BookToc(models.Model):
(LINE_TYPE, _('line'))
)
- version = models.ForeignKey(BookVersion, null=False, verbose_name=_("version"))
+ version = models.ForeignKey(BookVersion, on_delete=models.CASCADE, null=False, verbose_name=_("version"))
# book should be removed
- book = models.ForeignKey(Book, null=False, verbose_name=_("book"))
- parent = models.ForeignKey('self', null=True, blank=True, verbose_name=_("parent"))
+ book = models.ForeignKey(Book, on_delete=models.CASCADE, null=False, verbose_name=_("book"))
+ parent = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, verbose_name=_("parent"))
name = models.CharField(_('name'), max_length=2500, blank=True)
- chapter = models.ForeignKey(Chapter, null=True, blank=True, verbose_name=_("chapter"))
+ chapter = models.ForeignKey(Chapter, on_delete=models.CASCADE, null=True, blank=True, verbose_name=_("chapter"))
weight = models.IntegerField(_('weight'))
typeof = models.SmallIntegerField(_('typeof'), choices=TYPEOF_CHOICES)
@@ -784,8 +784,8 @@ def url_title(self):
return self.chapter.url_title
return None
- def __unicode__(self):
- return unicode(self.weight)
+ def __str__(self):
+ return str(self.weight)
class Meta:
verbose_name = _('Book TOC')
@@ -803,20 +803,20 @@ class BookiPermission(models.Model):
1 - admin
"""
- user = models.ForeignKey(auth_models.User, verbose_name=_("user"))
- book = models.ForeignKey(Book, null=True, verbose_name=_("book"))
- group = models.ForeignKey(BookiGroup, null=True, verbose_name=_("group"))
+ user = models.ForeignKey(auth_models.User, on_delete=models.CASCADE, verbose_name=_("user"))
+ book = models.ForeignKey(Book, on_delete=models.CASCADE, null=True, verbose_name=_("book"))
+ group = models.ForeignKey(BookiGroup, on_delete=models.CASCADE, null=True, verbose_name=_("group"))
permission = models.SmallIntegerField(_('permission'))
- def __unicode__(self):
+ def __str__(self):
return u'%s %s ' % (self.user.username, self.permission)
class AttributionExclude(models.Model):
- book = models.ForeignKey(Book, null=True, verbose_name=_("book"))
- user = models.ForeignKey(auth_models.User, verbose_name=_("user"))
+ book = models.ForeignKey(Book, on_delete=models.CASCADE, null=True, verbose_name=_("book"))
+ user = models.ForeignKey(auth_models.User, on_delete=models.CASCADE, verbose_name=_("user"))
- def __unicode__(self):
+ def __str__(self):
return u'%s' % (self.user.username, )
class Meta:
@@ -825,12 +825,12 @@ class Meta:
class PublishWizzard(models.Model):
- book = models.ForeignKey(Book, null=True, verbose_name=_("book"))
- user = models.ForeignKey(auth_models.User, verbose_name=_("user"))
+ book = models.ForeignKey(Book, on_delete=models.CASCADE, null=True, verbose_name=_("book"))
+ user = models.ForeignKey(auth_models.User, on_delete=models.CASCADE, verbose_name=_("user"))
wizz_type = models.CharField(_('wizard type'), max_length=20, blank=False)
wizz_options = models.TextField(_('wizard options'), default='', null=False)
- def __unicode__(self):
+ def __str__(self):
return u'%s' % (self.book.url_title, )
class Meta:
@@ -845,8 +845,8 @@ def upload_cover_to(att, filename):
class BookCover(models.Model):
- book = models.ForeignKey(Book, null=True, verbose_name=_("book"))
- user = models.ForeignKey(auth_models.User, verbose_name=_("user"))
+ book = models.ForeignKey(Book, on_delete=models.CASCADE, null=True, verbose_name=_("book"))
+ user = models.ForeignKey(auth_models.User, on_delete=models.CASCADE, verbose_name=_("user"))
cid = models.CharField('cid', max_length=40, null=False, default='', unique=True)
@@ -866,7 +866,7 @@ class BookCover(models.Model):
cover_type = models.CharField(_('Cover type'), max_length=20, blank=True)
creator = models.CharField(_('Cover'), max_length=40, blank=True)
- license = models.ForeignKey(License, null=True, verbose_name=_("license"))
+ license = models.ForeignKey(License, on_delete=models.CASCADE, null=True, verbose_name=_("license"))
notes = models.TextField(_('notes'))
@@ -879,7 +879,7 @@ def delete(self):
super(BookCover, self).delete()
- def __unicode__(self):
+ def __str__(self):
return u'%s' % (self.id, )
diff --git a/lib/booki/editor/south_migrations/0018_add_licenses_url.py b/lib/booki/editor/south_migrations/0018_add_licenses_url.py
index b4a022ba0..d96337eac 100644
--- a/lib/booki/editor/south_migrations/0018_add_licenses_url.py
+++ b/lib/booki/editor/south_migrations/0018_add_licenses_url.py
@@ -35,9 +35,9 @@ def forwards(self, orm):
license = orm.License.objects.get(pk=data['pk'])
license.url = data['url']
license.save()
- print "Updating url '%s' to license '%s'" % (data['url'], license.name)
+ print("Updating url '%s' to license '%s'" % (data['url'], license.name))
except orm.License.DoesNotExist:
- print "License with pk %s does not exist. Doing nothing" % data['pk']
+ print("License with pk %s does not exist. Doing nothing" % data['pk'])
def backwards(self, orm):
"Write your backwards methods here."
diff --git a/lib/booki/messaging/models.py b/lib/booki/messaging/models.py
index e4dbcd3c5..c29de7326 100644
--- a/lib/booki/messaging/models.py
+++ b/lib/booki/messaging/models.py
@@ -29,7 +29,7 @@ def uploadAttachmentTo(message, filename):
# XXX class "Message" with field "sender" would cause Django Admin to crash...
class Post(models.Model):
- sender = models.ForeignKey("Endpoint", verbose_name=_("sender"))
+ sender = models.ForeignKey("Endpoint", on_delete=models.CASCADE, verbose_name=_("sender"))
timestamp = models.DateTimeField(_('timestamp'), null=False, auto_now=True)
content = models.TextField(_('content'))
attachment = models.FileField(_('attachment'), upload_to=uploadAttachmentTo, max_length=2500)
@@ -54,7 +54,7 @@ def content_as_html(self):
res.append(part)
return " ".join(res)
- def __unicode__(self):
+ def __str__(self):
return u"%s-%s" % (self.sender, self.timestamp)
class Meta:
@@ -63,11 +63,11 @@ class Meta:
class PostAppearance(models.Model):
- post = models.ForeignKey('Post', verbose_name=_("post"))
+ post = models.ForeignKey('Post', on_delete=models.CASCADE, verbose_name=_("post"))
timestamp = models.DateTimeField(_('timestamp'), null=False)
- endpoint = models.ForeignKey('Endpoint', verbose_name=_('endpoint'))
+ endpoint = models.ForeignKey('Endpoint', on_delete=models.CASCADE, verbose_name=_('endpoint'))
- def __unicode__(self):
+ def __str__(self):
return u"%s-%s-%s" % (self.post.sender, self.endpoint, self.timestamp)
class Meta:
@@ -83,7 +83,7 @@ def match_wildcard(pattern, word):
class Endpoint(models.Model):
syntax = models.CharField(_('syntax'), max_length=2500, unique=True)
- config = models.ForeignKey('EndpointConfig', unique=True, null=True, blank=True)
+ config = models.ForeignKey('EndpointConfig', on_delete=models.CASCADE, unique=True, null=True, blank=True)
def as_user(self):
if not self.syntax.startswith("@"):
@@ -139,7 +139,7 @@ def wants_notification(self, message, word):
return True # no filters matched
- def __unicode__(self):
+ def __str__(self):
return self.syntax
class Meta:
@@ -149,7 +149,7 @@ class Meta:
class EndpointConfig(models.Model):
notification_filter = models.CharField(_('notification filter'), max_length=2500, blank=True)
- def __unicode__(self):
+ def __str__(self):
return u"config-"+"-".join(str(x) for x in self.endpoint_set.all())
class Meta:
@@ -157,10 +157,10 @@ class Meta:
verbose_name_plural = _('Endpoint configs')
class Following(models.Model):
- follower = models.ForeignKey('Endpoint', verbose_name=_("follower"), related_name='follower')
- target = models.ForeignKey('Endpoint', verbose_name=_("target"), related_name='target')
+ follower = models.ForeignKey('Endpoint', on_delete=models.CASCADE, verbose_name=_("follower"), related_name='follower')
+ target = models.ForeignKey('Endpoint', on_delete=models.CASCADE, verbose_name=_("target"), related_name='target')
- def __unicode__(self):
+ def __str__(self):
return u"%s-%s" % (self.follower, self.target)
class Meta:
diff --git a/lib/booki/messaging/views.py b/lib/booki/messaging/views.py
index c7f0c1605..1f162e70b 100644
--- a/lib/booki/messaging/views.py
+++ b/lib/booki/messaging/views.py
@@ -169,7 +169,7 @@ def add_appearance_for_tag(message, word, sent, direct=False, orig_word=None):
@login_required
def view_post(request):
if request.method != 'POST':
- return HttpResponse(unicode(_("Error")), content_type="text/plain")
+ return HttpResponse(str(_("Error")), content_type="text/plain")
# XXX validate:
content = request.POST.get('content', '')
@@ -215,7 +215,7 @@ def view_post(request):
if not ajax:
return redirect('view_profile', request.user.username)
else:
- return HttpResponse(unicode(_("Sent.")), content_type="text/plain")
+ return HttpResponse(str(_("Sent.")), content_type="text/plain")
@login_required
def view_follow(request):
diff --git a/lib/booki/utils/json_wrapper.py b/lib/booki/utils/json_wrapper.py
index 2f93e1366..ec1e4e547 100644
--- a/lib/booki/utils/json_wrapper.py
+++ b/lib/booki/utils/json_wrapper.py
@@ -14,15 +14,9 @@
# You should have received a copy of the GNU Affero General Public License
# along with Booktype. If not, see .
-"""In Python 2.5, the json module we use is an external module called
-'simplejson'. From Python 2.6, it is a standard module called 'json'.
-Just to complicate things, in Debian's Python 2.5, there is an
-entirely different module called 'json', so 'import json' might apeear
-to work there but do the worng thing.
-
-This module includes the logic for ensuring that the right module gets
-imported. For simplcity of backwards compatibility, the module it
-finds is called both 'simplejson' and 'json'.
+"""In Python 3, the json module is always available as a standard module.
+This module maintains backward compatibility with code that might still
+import from booki.utils.json_wrapper.
>>> from booki.utils.json_wrapper import json
>>> from booki.utils.json_wrapper import simplejson
@@ -30,14 +24,6 @@
True
"""
-try:
- import json
- if not hasattr(json, 'loads'):
- raise ImportError('accidentally imported the wrong json module.')
-except ImportError, e:
- from warnings import warn
- warn('json not found: "%s", trying simplejson' % e)
- del warn
- import simplejson as json
+import json
simplejson = json
diff --git a/lib/booktype/api/editor/views.py b/lib/booktype/api/editor/views.py
index 402e8adb0..804708513 100644
--- a/lib/booktype/api/editor/views.py
+++ b/lib/booktype/api/editor/views.py
@@ -611,7 +611,7 @@ def get(self, request, book_id, pk, format=None):
Role.objects.get(name='registered_users')
).data)
- print Role.objects.get(name='registered_users').permissions
+ print(Role.objects.get(name='registered_users').permissions)
# get book roles
for role in user.roles.filter(book=book):
diff --git a/lib/booktype/api/management/commands/generate_filters.py b/lib/booktype/api/management/commands/generate_filters.py
index a5b9fe931..08615e94a 100644
--- a/lib/booktype/api/management/commands/generate_filters.py
+++ b/lib/booktype/api/management/commands/generate_filters.py
@@ -215,4 +215,4 @@ def handle(self, *args, **options):
"\n model = {0}" \
"\n fields = {1}\n".format(model.__name__, tuple(filters))
- print result
+ print(result)
diff --git a/lib/booktype/apps/account/models.py b/lib/booktype/apps/account/models.py
index 30f3f55b3..4cfb5a56f 100644
--- a/lib/booktype/apps/account/models.py
+++ b/lib/booktype/apps/account/models.py
@@ -45,7 +45,7 @@ def remove_image(self):
try:
os.remove('%s/%s%s.jpg' % (settings.MEDIA_ROOT, settings.PROFILE_IMAGE_UPLOAD_DIR, self.user.username))
except Exception as err:
- print err
+ print(err)
class UserPassword(models.Model):
@@ -61,7 +61,7 @@ class UserPassword(models.Model):
@ivar host: Client host.
"""
- user = models.ForeignKey(User, unique=False, verbose_name=_("user"))
+ user = models.ForeignKey(User, on_delete=models.CASCADE, unique=False, verbose_name=_("user"))
secretcode = models.CharField(_('secretcode'), max_length=30, blank=False, null=False)
created = models.DateTimeField(_('created'), auto_now=True)
diff --git a/lib/booktype/apps/account/utils.py b/lib/booktype/apps/account/utils.py
index 0ca0caa46..a4b0ba57a 100644
--- a/lib/booktype/apps/account/utils.py
+++ b/lib/booktype/apps/account/utils.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-import urllib
-import urlparse
+from urllib import parse as urllib_parse, request as urllib_request
+from urllib import parse as urlparse
import hashlib
from django.conf import settings
@@ -35,7 +35,7 @@ def get_profile_image(user, size=100):
hashlib.md5(
profile.user.email.encode('utf-8').lower()
).hexdigest(),
- urllib.urlencode({'d': default, 's': str(size)})
+ urlparse.urlencode({'d': default, 's': str(size)})
)
filename = profile.image.name
diff --git a/lib/booktype/apps/convert/tasks.py b/lib/booktype/apps/convert/tasks.py
index bc5d6fd2b..c922d5215 100644
--- a/lib/booktype/apps/convert/tasks.py
+++ b/lib/booktype/apps/convert/tasks.py
@@ -102,7 +102,7 @@ def convert(request_data, base_path):
assets.add_files(request_data.files)
subtasks = []
- for (name, output) in request_data.outputs.iteritems():
+ for (name, output) in request_data.outputs.items():
sandbox_path = os.path.join(base_path, name)
output_path = os.path.join(sandbox_path, output.output)
@@ -129,7 +129,7 @@ def convert(request_data, base_path):
with allow_join_result():
result.join(propagate=False)
- subtasks_info = {async.task_id: async for async in result.children}
+ subtasks_info = {task.task_id: task for task in result.children}
celery.current_task.update_state(state="PROGRESS", meta=subtasks_info)
return subtasks_info
diff --git a/lib/booktype/apps/convert/templatetags/convert_tags.py b/lib/booktype/apps/convert/templatetags/convert_tags.py
index 212d48f1c..c6a955a51 100644
--- a/lib/booktype/apps/convert/templatetags/convert_tags.py
+++ b/lib/booktype/apps/convert/templatetags/convert_tags.py
@@ -16,8 +16,8 @@ def find_with_key(data, key, value):
Returns metadata entries
"""
- for k, v in data.iteritems():
- for a, b in v.iteritems():
+ for k, v in data.items():
+ for a, b in v.items():
for c in b:
if c[1].get(key, '') == value:
yield c
@@ -79,8 +79,8 @@ def get_metadata(data, name):
Returns metadata entry.
"""
- for k, v in data.iteritems():
- for a, b in v.iteritems():
+ for k, v in data.items():
+ for a, b in v.items():
if a == name:
if len(b) > 0 and len(b[0]) > 0:
return b[0][0]
diff --git a/lib/booktype/apps/convert/views.py b/lib/booktype/apps/convert/views.py
index 4f09697ad..5b1f9dfd8 100644
--- a/lib/booktype/apps/convert/views.py
+++ b/lib/booktype/apps/convert/views.py
@@ -50,7 +50,7 @@ def __init__(self, data):
self.assets = data.get("assets", {}) # TODO: check type is dict
self.input = data["input"]
self.outputs = {
- k: OutputData(v) for (k, v) in data["outputs"].iteritems()
+ k: OutputData(v) for (k, v) in data["outputs"].items()
}
@@ -72,7 +72,7 @@ def post(self, request):
# name:path for all uploaded files
request_data.files = {
field_name: _file.file_path()
- for (field_name, _file) in request.FILES.iteritems()
+ for (field_name, _file) in request.FILES.items()
}
# start the task in the background
@@ -101,7 +101,7 @@ def get_task_name(async_result):
if task_result:
task_info["result"] = {
get_task_name(subtask): get_task_info(subtask)
- for (_n, subtask) in task_result.iteritems()
+ for (_n, subtask) in task_result.items()
}
response_data = task_info
diff --git a/lib/booktype/apps/core/management/commands/update_default_roles.py b/lib/booktype/apps/core/management/commands/update_default_roles.py
index d6a546cfd..ce190d10c 100644
--- a/lib/booktype/apps/core/management/commands/update_default_roles.py
+++ b/lib/booktype/apps/core/management/commands/update_default_roles.py
@@ -31,4 +31,4 @@ def handle(self, *args, **options):
raise CommandError(err_msg)
statuses = ['updated', 'created']
- print 'Role %s has been %s.' % (role_name, statuses[created])
+ print('Role %s has been %s.' % (role_name, statuses[created]))
diff --git a/lib/booktype/apps/core/management/commands/update_permissions.py b/lib/booktype/apps/core/management/commands/update_permissions.py
index ee978c4f6..228fbdefc 100644
--- a/lib/booktype/apps/core/management/commands/update_permissions.py
+++ b/lib/booktype/apps/core/management/commands/update_permissions.py
@@ -33,7 +33,7 @@ def handle(self, *args, **options):
if options['delete_orphans']:
orphan_perms.delete()
- print BOLD_ON + "All undeclared permissions has been deleted." + BOLD_OFF
+ print(BOLD_ON + "All undeclared permissions has been deleted." + BOLD_OFF)
else:
if orphan_perms.count() > 0:
suggestion = (
@@ -41,4 +41,4 @@ def handle(self, *args, **options):
"To delete them use: \n"
"./manage.py update_permissions --delete-orphans"
)
- print BOLD_ON + suggestion % orphan_perms.count() + BOLD_OFF
+ print(BOLD_ON + suggestion % orphan_perms.count() + BOLD_OFF)
diff --git a/lib/booktype/apps/core/models.py b/lib/booktype/apps/core/models.py
index eaa0cd653..749d0cf4d 100644
--- a/lib/booktype/apps/core/models.py
+++ b/lib/booktype/apps/core/models.py
@@ -20,7 +20,7 @@ class Permission(models.Model):
max_length=255
)
- def __unicode__(self):
+ def __str__(self):
return self.label
class Meta:
@@ -62,7 +62,7 @@ class Role(models.Model):
blank=True, null=True
)
- def __unicode__(self):
+ def __str__(self):
return u'%s' % self.name
class Meta:
@@ -81,15 +81,15 @@ class BookRole(models.Model):
Roles scoped by the desired Book
"""
- role = models.ForeignKey(Role, verbose_name=_('role'))
- book = models.ForeignKey(Book, verbose_name=_('book'))
+ role = models.ForeignKey(Role, on_delete=models.CASCADE, verbose_name=_('role'))
+ book = models.ForeignKey(Book, on_delete=models.CASCADE, verbose_name=_('book'))
members = models.ManyToManyField(
User, verbose_name=_('users'),
blank=True, null=True,
related_name='roles'
)
- def __unicode__(self):
+ def __str__(self):
return u'%s %s' % (self.book.title, self.role.name)
class Meta:
@@ -130,7 +130,7 @@ class BookSkeleton(models.Model):
upload_to=SKELETON_UPLOAD_DIR,
verbose_name=_('File'))
- def __unicode__(self):
+ def __str__(self):
return u'{0} - {1}'.format(self.name, self.language)
class Meta:
diff --git a/lib/booktype/apps/edit/channel.py b/lib/booktype/apps/edit/channel.py
index 8eea0b17c..c96f6a3b4 100644
--- a/lib/booktype/apps/edit/channel.py
+++ b/lib/booktype/apps/edit/channel.py
@@ -1355,13 +1355,13 @@ def remote_chapters_changed(request, message, bookid, version):
id__exact=int(chap[1]),
version=book_version
)
- except Exception, e:
+ except Exception as e:
pass
toc_item.parent = parent
toc_item.save()
- except Exception, e:
- print e
+ except Exception as e:
+ print(e)
weight -= 1
diff --git a/lib/booktype/apps/edit/models.py b/lib/booktype/apps/edit/models.py
index 8ff119e40..aa78476de 100644
--- a/lib/booktype/apps/edit/models.py
+++ b/lib/booktype/apps/edit/models.py
@@ -12,7 +12,7 @@ class Comment(models.Model):
"""Model for storing Word comments"""
# Every comment is connected with certain chapter document
- chapter = models.ForeignKey(Chapter, null=False, verbose_name="chapter")
+ chapter = models.ForeignKey(Chapter, on_delete=models.CASCADE, null=False, verbose_name="chapter")
# Comments can have parents. This is when one user participates in the discussion
parent = models.ForeignKey('self', null=True, on_delete=models.SET_NULL)
@@ -24,7 +24,7 @@ class Comment(models.Model):
author = models.CharField("author", max_length=50, default='', null=False)
# user who created the comment if any
- user = models.ForeignKey(User, null=True)
+ user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
# Date when comments was written
date = models.DateTimeField("date", null=False)
@@ -82,7 +82,7 @@ class InviteCode(models.Model):
"""
code = models.CharField(max_length=20, unique=True, db_index=True)
- book = models.ForeignKey(Book, related_name='invite_codes')
+ book = models.ForeignKey(Book, on_delete=models.CASCADE, related_name='invite_codes')
roles = models.ManyToManyField(Role, verbose_name='Roles to assign')
created = models.DateTimeField(auto_now_add=True)
expire_on = models.DateField()
@@ -103,7 +103,7 @@ class ChatThread(models.Model):
In future book can have more than 1 thread,
that is why we have this proxy model.
"""
- book = models.ForeignKey(Book)
+ book = models.ForeignKey(Book, on_delete=models.CASCADE)
def __str__(self):
return '"{}" thread.'.format(self.book.title)
@@ -113,8 +113,8 @@ class ChatMessage(models.Model):
"""
Chat message.
"""
- thread = models.ForeignKey(ChatThread, related_name='messages')
- sender = models.ForeignKey(User)
+ thread = models.ForeignKey(ChatThread, on_delete=models.CASCADE, related_name='messages')
+ sender = models.ForeignKey(User, on_delete=models.CASCADE)
text = models.TextField()
datetime = models.DateTimeField(auto_now_add=True, db_index=True)
diff --git a/lib/booktype/apps/edit/tasks.py b/lib/booktype/apps/edit/tasks.py
index 54eb275b8..9d66e6a70 100644
--- a/lib/booktype/apps/edit/tasks.py
+++ b/lib/booktype/apps/edit/tasks.py
@@ -110,7 +110,7 @@ def publish_book(*args, **kwargs):
logger.debug(data)
output_results = {}
- # _format: False for _format in data["outputs"].iterkeys()}
+ # _format: False for _format in data["outputs"].keys()}
convert_url = '{}/_convert/'.format(settings.CONVERT_URL)
result = download.fetch_url(convert_url, data, method='POST')
@@ -157,7 +157,7 @@ def publish_book(*args, **kwargs):
'Could not communicate with a server to fetch polling data.')
if dta['state'] == 'SUCCESS':
- for _key in data["outputs"].iterkeys():
+ for _key in data["outputs"].keys():
if 'state' in dta['result'][_key]:
if dta['result'][_key]['state'] == 'SUCCESS':
output_results[_key] = True
@@ -187,7 +187,7 @@ def publish_book(*args, **kwargs):
_files = {}
- for output_type, result in dta['result'].iteritems():
+ for output_type, result in dta['result'].items():
if 'state' in result:
if result['state'] == 'SUCCESS':
status = 0
diff --git a/lib/booktype/apps/edit/views.py b/lib/booktype/apps/edit/views.py
index da08a7933..55a9f34ac 100644
--- a/lib/booktype/apps/edit/views.py
+++ b/lib/booktype/apps/edit/views.py
@@ -801,10 +801,10 @@ def form_valid(self, form):
else:
error, message = True, _('You have no permissions to execute this action.')
except Exception as err:
- print err
+ print(err)
error, message = True, _('Unknown error while saving changes.')
- return self.render_json_response({'message': unicode(message), 'error': error,
+ return self.render_json_response({'message': str(message), 'error': error,
'updated_settings': updated_settings})
def form_invalid(self, form):
diff --git a/lib/booktype/apps/export/models.py b/lib/booktype/apps/export/models.py
index ca36ec617..70313c544 100644
--- a/lib/booktype/apps/export/models.py
+++ b/lib/booktype/apps/export/models.py
@@ -33,8 +33,8 @@
class BookExport(models.Model):
- version = models.ForeignKey(BookVersion, null=False, verbose_name=_("export"))
- user = models.ForeignKey(auth_models.User, verbose_name=_("user"), null=True)
+ version = models.ForeignKey(BookVersion, on_delete=models.CASCADE, null=False, verbose_name=_("export"))
+ user = models.ForeignKey(auth_models.User, on_delete=models.CASCADE, verbose_name=_("user"), null=True)
name = models.CharField(_('Name'), max_length=100, blank=False)
task_id = models.CharField(_('Task ID'), max_length=64, null=False, unique=True, db_index=True)
created = models.DateTimeField(_('Created'), auto_now=False, default=datetime.datetime.now)
@@ -51,7 +51,7 @@ def book_title(self):
class ExportFile(models.Model):
- export = models.ForeignKey(BookExport, null=False, verbose_name=_("export"))
+ export = models.ForeignKey(BookExport, on_delete=models.CASCADE, null=False, verbose_name=_("export"))
typeof = models.CharField(_('Export type'), max_length=20, blank=False, null=False)
filesize = models.IntegerField(_('File size'), default=0, null=True)
pages = models.IntegerField(_('Number of pages'), default=0, null=True)
@@ -85,8 +85,8 @@ def _exportfile_delete(sender, instance, **kwargs):
class ExportComment(models.Model):
- export = models.ForeignKey(BookExport, null=False, verbose_name=_("version"))
- user = models.ForeignKey(auth_models.User, verbose_name=_("user"))
+ export = models.ForeignKey(BookExport, on_delete=models.CASCADE, null=False, verbose_name=_("version"))
+ user = models.ForeignKey(auth_models.User, on_delete=models.CASCADE, verbose_name=_("user"))
created = models.DateTimeField(_('Created'), auto_now=False, default=datetime.datetime.now)
content = models.TextField(_('Content'), default='')
@@ -96,7 +96,7 @@ class Meta:
class ExportSettings(models.Model):
- book = models.ForeignKey(Book, null=False, verbose_name=_("book"))
+ book = models.ForeignKey(Book, on_delete=models.CASCADE, null=False, verbose_name=_("book"))
typeof = models.CharField(_('Export type'), max_length=20, blank=False, null=False)
data = models.TextField(_('Data'), default='{}', null=False)
created = models.DateTimeField(_('Created'), auto_now=False, default=datetime.datetime.now)
diff --git a/lib/booktype/apps/export/utils.py b/lib/booktype/apps/export/utils.py
index fe842e459..4b8303e73 100644
--- a/lib/booktype/apps/export/utils.py
+++ b/lib/booktype/apps/export/utils.py
@@ -18,7 +18,7 @@
import os
import json
import logging
-import urlparse
+from urllib import parse as urlparse
from lxml import etree
from collections import OrderedDict
diff --git a/lib/booktype/apps/loadsave/management/commands/bookload.py b/lib/booktype/apps/loadsave/management/commands/bookload.py
index 3b53554dc..9931b5d43 100644
--- a/lib/booktype/apps/loadsave/management/commands/bookload.py
+++ b/lib/booktype/apps/loadsave/management/commands/bookload.py
@@ -63,4 +63,4 @@ def handle(self, *args, **options):
raise CommandError('File "%s" does not exist. Can not finish import.' % fileName)
else:
if options['verbosity'] in ['1', '2']:
- print 'Booki-zip "%s" file successfully imported.' % fileName
+ print('Booki-zip "%s" file successfully imported.' % fileName)
diff --git a/lib/booktype/apps/loadsave/management/commands/booksave.py b/lib/booktype/apps/loadsave/management/commands/booksave.py
index 72ceb4a12..2dc74bff9 100644
--- a/lib/booktype/apps/loadsave/management/commands/booksave.py
+++ b/lib/booktype/apps/loadsave/management/commands/booksave.py
@@ -58,4 +58,4 @@ def handle(self, *args, **options):
get_exporter_class()(filename, book_version).run()
if options['verbosity'] in ['1', '2']:
- print 'Book successfully exported into "%s" file.' % filename
+ print('Book successfully exported into "%s" file.' % filename)
diff --git a/lib/booktype/apps/portal/forms.py b/lib/booktype/apps/portal/forms.py
index 7853a5722..b5623d164 100644
--- a/lib/booktype/apps/portal/forms.py
+++ b/lib/booktype/apps/portal/forms.py
@@ -14,8 +14,8 @@
class SpanErrorList(ErrorList):
- def __unicode__(self):
- return unicode(self.as_spans())
+ def __str__(self):
+ return str(self.as_spans())
def as_spans(self):
return "%s" % (
@@ -72,7 +72,7 @@ def set_group_image(self, group_id, group_image):
misc.set_group_image("{}_small".format(group_id), group_image, 18, 18)
except Exception as err:
# TODO: we should do something here
- print err
+ print(err)
class GroupCreateForm(BaseGroupForm):
diff --git a/lib/booktype/apps/portal/views.py b/lib/booktype/apps/portal/views.py
index 2da30c40d..db5f3cbc3 100644
--- a/lib/booktype/apps/portal/views.py
+++ b/lib/booktype/apps/portal/views.py
@@ -341,7 +341,7 @@ def delete(self, request, *args, **kwargs):
try:
group.remove_group_images()
except Exception as e:
- print e
+ print(e)
messages.success(self.request, _('Group successfully deleted.'))
return super(GroupDeleteView, self).delete(request, *args, **kwargs)
diff --git a/lib/booktype/apps/reader/templatetags/reader_tags.py b/lib/booktype/apps/reader/templatetags/reader_tags.py
index 72f0a8e44..5fcd0fbf6 100644
--- a/lib/booktype/apps/reader/templatetags/reader_tags.py
+++ b/lib/booktype/apps/reader/templatetags/reader_tags.py
@@ -53,7 +53,7 @@ def verbose_activity(activity):
fields to it.
"""
- verbose = unicode(ACTIVITY_KIND_VERBOSE.get(activity.kind, None))
+ verbose = str(ACTIVITY_KIND_VERBOSE.get(activity.kind, None))
default_image = static('core/img/chapter-default.png')
link_url = None
book = activity.book
diff --git a/lib/booktype/apps/reader/views.py b/lib/booktype/apps/reader/views.py
index ce010befb..99a12137f 100644
--- a/lib/booktype/apps/reader/views.py
+++ b/lib/booktype/apps/reader/views.py
@@ -187,7 +187,7 @@ def form_valid(self, form):
self.object.set_cover(fname)
os.unlink(fname)
self.object.save()
- except Exception, e:
+ except Exception as e:
logger.exception(e)
all_ok = False
diff --git a/lib/booktype/apps/themes/templatetags/themes.py b/lib/booktype/apps/themes/templatetags/themes.py
index 107c95bfd..8a716f826 100644
--- a/lib/booktype/apps/themes/templatetags/themes.py
+++ b/lib/booktype/apps/themes/templatetags/themes.py
@@ -31,11 +31,10 @@ def list_theme_options(context):
for theme in os.listdir('{}/themes/'.format(settings.BOOKTYPE_ROOT)):
if os.path.isdir('{}/themes/{}/'.format(settings.BOOKTYPE_ROOT, theme)):
if os.path.exists('{}/themes/{}/panel.html'.format(settings.BOOKTYPE_ROOT, theme)):
- f = open('{}/themes/{}/panel.html'.format(settings.BOOKTYPE_ROOT, theme), 'rt')
- s = f.read()
- f.close()
+ with open('{}/themes/{}/panel.html'.format(settings.BOOKTYPE_ROOT, theme), 'rt', encoding='utf-8') as f:
+ s = f.read()
- t = Template(unicode(s, 'utf8'))
+ t = Template(s)
content = t.render(context)
options.append({'name': theme, 'content': content})
diff --git a/lib/booktype/contrib/legacy/bookizip.py b/lib/booktype/contrib/legacy/bookizip.py
index 0f9a99af0..622625f51 100644
--- a/lib/booktype/contrib/legacy/bookizip.py
+++ b/lib/booktype/contrib/legacy/bookizip.py
@@ -41,7 +41,7 @@ def get_chapters(self):
chapters = []
- for key, value in info['manifest'].iteritems():
+ for key, value in info['manifest'].items():
if value['mimetype'] in ['text/html', 'application/xhtml+xml']:
chapters.append(value['url'])
@@ -52,7 +52,7 @@ def get_attachments(self):
chapters = []
- for key, value in info['manifest'].iteritems():
+ for key, value in info['manifest'].items():
if value['mimetype'] in ['image/png', 'image/jpeg', 'image/gif', 'image/tiff']:
chapters.append(value['url'])
diff --git a/lib/booktype/contrib/legacy/views.py b/lib/booktype/contrib/legacy/views.py
index 1905f4ec6..cd3a99182 100644
--- a/lib/booktype/contrib/legacy/views.py
+++ b/lib/booktype/contrib/legacy/views.py
@@ -24,9 +24,9 @@
import time
import requests
import logging
-import urlparse
+from urllib import parse as urlparse
-from StringIO import StringIO
+from io import StringIO
from collections import OrderedDict
from django.views.generic.base import View
@@ -91,7 +91,7 @@ def export_book(input_file, filename):
title=title,
file_name='{}.xhtml'.format(file_name[6:-5])
)
- cont = unicode(bookizip.read(file_name), 'utf-8')
+ cont = str(bookizip.read(file_name), 'utf-8')
_section.append(c1)
try:
@@ -274,7 +274,7 @@ def send_request(book_url, conf, request):
logger.exception('Could not read response data.')
if dta['state'] == 'SUCCESS':
- for _key in data["outputs"].iterkeys():
+ for _key in data["outputs"].keys():
if 'state' in dta['result'][_key]:
if dta['result'][_key]['state'] == 'SUCCESS':
output_results[_key] = True
@@ -289,13 +289,13 @@ def _x(_key):
d['status'] = output_results[_key]
return d
- urls = {_key: _x(_key) for _key in output_results.iterkeys()}
+ urls = {_key: _x(_key) for _key in output_results.keys()}
_now = datetime.datetime.now()
_files = {}
- for output_type, result in dta['result'].iteritems():
+ for output_type, result in dta['result'].items():
if 'state' in result:
if result['state'] == 'SUCCESS':
return result
diff --git a/lib/booktype/convert/assets.py b/lib/booktype/convert/assets.py
index 1122f99d1..515984c2a 100644
--- a/lib/booktype/convert/assets.py
+++ b/lib/booktype/convert/assets.py
@@ -29,11 +29,11 @@ def __init__(self, base_path):
self.files = {}
def add_files(self, files):
- for (asset_id, file_path) in files.iteritems():
+ for (asset_id, file_path) in files.items():
self.files[asset_id] = AssetFile(asset_id, file_path)
def add_urls(self, urls):
- for (asset_id, url) in urls.iteritems():
+ for (asset_id, url) in urls.items():
file_path = os.path.join(self.base_path, slugify(asset_id))
download(url, file_path)
self.files[asset_id] = AssetFile(asset_id, file_path, original_url=url)
diff --git a/lib/booktype/convert/epub/converter.py b/lib/booktype/convert/epub/converter.py
index b3c7bed3e..64347fdb0 100644
--- a/lib/booktype/convert/epub/converter.py
+++ b/lib/booktype/convert/epub/converter.py
@@ -18,7 +18,7 @@
import uuid
import json
import logging
-import urlparse
+from urllib import parse as urlparse
import ebooklib
import datetime
from copy import deepcopy
@@ -236,10 +236,10 @@ def _edit_metadata(self, epub_book):
# delete existing 'modified' tag
m = epub_book.metadata[ebooklib.epub.NAMESPACES["OPF"]]
- m[None] = filter(lambda (_, x): not (isinstance(x, dict) and x.get("property") == "dcterms:modified"), m[None]) # noqa
+ m[None] = list(filter(lambda item: not (isinstance(item[1], dict) and item[1].get("property") == "dcterms:modified"), m[None])) # noqa
# we also need to remove the `additional metadata` which here is just garbage
- m[None] = filter(lambda (_, x): not (isinstance(x, dict) and x.get("property").startswith("add_meta_terms:")), m[None]) # noqa
+ m[None] = list(filter(lambda item: not (isinstance(item[1], dict) and item[1].get("property") and item[1].get("property").startswith("add_meta_terms:")), m[None])) # noqa
# NOTE: probably going to extend this function in future
@@ -439,7 +439,7 @@ def _get_theme_assets(self):
def _add_theme_assets(self, epub_book):
assets = self._get_theme_assets()
- for asset_type, asset_list in assets.iteritems():
+ for asset_type, asset_list in assets.items():
if asset_type == 'images':
for image_name in asset_list:
name = os.path.basename(image_name)
diff --git a/lib/booktype/convert/epub/writerplugins/base_writerplugin.py b/lib/booktype/convert/epub/writerplugins/base_writerplugin.py
index ebaf4e1a6..983e28c09 100644
--- a/lib/booktype/convert/epub/writerplugins/base_writerplugin.py
+++ b/lib/booktype/convert/epub/writerplugins/base_writerplugin.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
import os
-import urllib
-import urlparse
+from urllib import parse as urllib_parse, request as urllib_request
+from urllib import parse as urlparse
import ebooklib
import logging
@@ -85,7 +85,7 @@ def _fix_images(self, root):
if not src:
continue
- path = urllib.unquote(src)
+ path = urlparse.unquote(src)
# if hostname, then it is an image with absolute url
if urlparse.urlparse(path).hostname:
diff --git a/lib/booktype/convert/loader.py b/lib/booktype/convert/loader.py
index 293bba310..fea9b04a6 100644
--- a/lib/booktype/convert/loader.py
+++ b/lib/booktype/convert/loader.py
@@ -67,7 +67,7 @@ def allowed_module(klass, module_name):
for module_name in module_names:
try:
module = importlib.import_module(module_name)
- except Exception, e:
+ except Exception as e:
print("could not load module %s: %s" % (module_name, e))
continue
diff --git a/lib/booktype/convert/mpdf/converter.py b/lib/booktype/convert/mpdf/converter.py
index acf577654..573f4f464 100644
--- a/lib/booktype/convert/mpdf/converter.py
+++ b/lib/booktype/convert/mpdf/converter.py
@@ -18,7 +18,7 @@
import json
import uuid
import codecs
-import urllib2
+from urllib import request as urllib2
import logging
import datetime
from lxml import etree
@@ -266,7 +266,7 @@ def get_metadata(self, book):
dc_metadata = {
key: value[0][0] for key, value in
- book.metadata.get("http://purl.org/dc/elements/1.1/").iteritems()
+ book.metadata.get("http://purl.org/dc/elements/1.1/").items()
}
m = book.metadata[ebooklib.epub.NAMESPACES["OPF"]]
@@ -539,9 +539,8 @@ def _write_configuration(self, book):
data = {'metadata': dc_metadata, 'config': self.config}
data.update(self.get_extra_configuration())
- f = codecs.open('{}/config.json'.format(self.sandbox_path), 'wt', 'utf8')
- f.write(unicode(json.dumps(data), 'utf8'))
- f.close()
+ with codecs.open('{}/config.json'.format(self.sandbox_path), 'wt', 'utf8') as f:
+ f.write(json.dumps(data))
def _save_images(self, book):
"""Saves all the images from EPUB file to the temporary directory.
@@ -809,7 +808,7 @@ def _write(name, content):
except IOError:
pass
- for asset_type, asset_list in assets.iteritems():
+ for asset_type, asset_list in assets.items():
if asset_type == 'images':
for image_name in asset_list:
name = os.path.basename(image_name)
diff --git a/lib/booktype/convert/pdf/bookjs.py b/lib/booktype/convert/pdf/bookjs.py
index d0a3a0333..2f6839c79 100644
--- a/lib/booktype/convert/pdf/bookjs.py
+++ b/lib/booktype/convert/pdf/bookjs.py
@@ -34,7 +34,7 @@ def render(html_path, pdf_path, **kwargs):
"-output", pdf_path,
]
- if kwargs.has_key("page_config"):
+ if "page_config" in kwargs:
params += ["-page-config", kwargs.get("page_config")]
custom_css_file = None
@@ -93,8 +93,8 @@ def unit(x):
def _get_page_settings(args):
settings = {}
- for key, (min_val, max_val, multiplier) in constants.PAGE_EXTREMA.iteritems():
- if not args.has_key(key):
+ for key, (min_val, max_val, multiplier) in constants.PAGE_EXTREMA.items():
+ if key not in args:
continue
val = float(args.get(key))
@@ -104,10 +104,10 @@ def _get_page_settings(args):
else:
settings[key] = val * multiplier
- if args.has_key("page_size"):
+ if "page_size" in args:
page_size = args.get("page_size")
- if constants.PAGE_SIZE_DATA.has_key(page_size):
+ if page_size in constants.PAGE_SIZE_DATA:
settings.update(constants.PAGE_SIZE_DATA.get(page_size))
else:
raise ValueError("invalid page size specifier")
diff --git a/lib/booktype/convert/pdf/converter.py b/lib/booktype/convert/pdf/converter.py
index 0320be2fb..3e0daad3c 100644
--- a/lib/booktype/convert/pdf/converter.py
+++ b/lib/booktype/convert/pdf/converter.py
@@ -22,7 +22,7 @@
import lxml.html
from lxml import etree
-import urllib2
+from urllib import request as urllib2
import logging
@@ -71,7 +71,7 @@ def __init__(self, *args, **kwargs):
def convert(self, book, output_path):
self._save_images(book)
- dc_metadata = {key : value[0][0] for (key, value) in book.metadata.get("http://purl.org/dc/elements/1.1/").iteritems()}
+ dc_metadata = {key : value[0][0] for (key, value) in book.metadata.get("http://purl.org/dc/elements/1.1/").items()}
head_params = {
"title" : dc_metadata.get("title", ""),
diff --git a/lib/booktype/convert/runner.py b/lib/booktype/convert/runner.py
index 509b23e26..9d40d8419 100644
--- a/lib/booktype/convert/runner.py
+++ b/lib/booktype/convert/runner.py
@@ -39,7 +39,7 @@ def run_conversion(profile, input, output, config=None, sandbox_path=None, asset
if converters is None:
converters = loader.find_all()
- if not converters.has_key(profile):
+ if profile not in converters:
raise ConversionError("no converter registered for " + profile)
book_asset = assets.get(input)
diff --git a/lib/booktype/convert/xhtml/converter.py b/lib/booktype/convert/xhtml/converter.py
index dd3acd398..f651d5f05 100644
--- a/lib/booktype/convert/xhtml/converter.py
+++ b/lib/booktype/convert/xhtml/converter.py
@@ -16,8 +16,8 @@
import os
import logging
-import urlparse
-import urllib
+from urllib import parse as urlparse
+from urllib import parse as urllib_parse, request as urllib_request
import zipfile
import ebooklib
@@ -162,7 +162,7 @@ def _fix_images(self, root):
for element in root.iter('img'):
- path = urllib.unquote(element.get('src'))
+ path = urlparse.unquote(element.get('src'))
# if hostname, then it is an image with absolute url
if urlparse.urlparse(path).hostname:
diff --git a/lib/booktype/importer/docx/docximporter.py b/lib/booktype/importer/docx/docximporter.py
index e7e81705f..75f92a689 100644
--- a/lib/booktype/importer/docx/docximporter.py
+++ b/lib/booktype/importer/docx/docximporter.py
@@ -180,7 +180,7 @@ def _import_attachments(self, book, doc):
unimportable_image = False
not_supported = False
- for rel_id, rel_value in doc.relationships['document'].iteritems():
+ for rel_id, rel_value in doc.relationships['document'].items():
if rel_value.get('type', '') == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image':
att = models.Attachment(book=book, version=book.version, status=stat)
diff --git a/lib/booktype/importer/epub/epubimporter.py b/lib/booktype/importer/epub/epubimporter.py
index 65dc01ab9..f88dcef30 100644
--- a/lib/booktype/importer/epub/epubimporter.py
+++ b/lib/booktype/importer/epub/epubimporter.py
@@ -17,11 +17,11 @@
import os
import uuid
import pprint
-import urllib
+from urllib import parse as urllib_parse, request as urllib_request
import difflib
import logging
import hashlib
-import urlparse
+from urllib import parse as urlparse
import datetime
import lxml.html
@@ -103,7 +103,7 @@ def _parse_toc(elements, parent=None):
_parse_toc(_elem[1], unique_id)
elif isinstance(_elem, ebooklib.epub.Link):
_urlp = urlparse.urlparse(_elem.href)
- _name = os.path.normpath(urllib.unquote(_urlp.path))
+ _name = os.path.normpath(urlparse.unquote(_urlp.path))
# check in case _name is an empty string
if not _name:
@@ -228,15 +228,15 @@ def _make_url_title(title, i=0):
"Imported chapter: {} -> {}".format(document, chapter))
# fix links to chapters
- for file_name, chapter in self._chapters.iteritems():
+ for file_name, chapter in self._chapters.items():
self._fix_links(chapter, base_path=os.path.dirname(file_name))
# create TOC objects
self._make_toc(book, toc)
def _create_content(self, document, title):
- if not isinstance(title, unicode):
- title = unicode(title, 'utf-8')
+ if isinstance(title, bytes):
+ title = title.decode('utf-8')
content = document.get_body_content()
@@ -288,7 +288,7 @@ def _find_heading(self, tree, title):
return None
def matches(heading):
- heading_text = unicode(
+ heading_text = str(
etree.tostring(heading, method='text', encoding='utf-8'),
'utf-8'
)
@@ -468,7 +468,7 @@ def _fix_links(self, chapter, base_path):
urlp = urlparse.urlparse(href)
name = os.path.normpath(
- os.path.join(base_path, urllib.unquote(urlp.path)))
+ os.path.join(base_path, urlparse.unquote(urlp.path)))
if name in self._chapters:
title = self._chapters[name].url_title
@@ -488,7 +488,7 @@ def _fix_links(self, chapter, base_path):
urlp = urlparse.urlparse(src)
name = os.path.normpath(
- os.path.join(base_path, urllib.unquote(urlp.path)))
+ os.path.join(base_path, urlparse.unquote(urlp.path)))
if urlp.netloc:
continue
@@ -498,7 +498,7 @@ def _fix_links(self, chapter, base_path):
self._attachments[name].attachment.name)
attName, attExt = os.path.splitext(file_name)
- fixed_src = urllib.quote(
+ fixed_src = urlparse.quote(
'static/{}{}'.format(booktype_slugify(attName), attExt))
image.set('src', fixed_src)
to_save = True
diff --git a/lib/booktype/utils/book.py b/lib/booktype/utils/book.py
index e3c7a3c68..dd0849001 100644
--- a/lib/booktype/utils/book.py
+++ b/lib/booktype/utils/book.py
@@ -226,7 +226,7 @@ def set_book_cover(book, file_name):
# If we have used book.cover.save we would end up with obsolete files on disk
book.cover = '%s%s.jpg' % (settings.COVER_IMAGE_UPLOAD_DIR, book.id)
- except Exception, e:
+ except Exception as e:
logger.exception(e)
diff --git a/lib/booktype/utils/misc.py b/lib/booktype/utils/misc.py
index 670342557..a57409f2c 100644
--- a/lib/booktype/utils/misc.py
+++ b/lib/booktype/utils/misc.py
@@ -15,14 +15,14 @@
# along with Booktype. If not, see .
import os
-import urllib
+from urllib import parse as urllib_parse, request as urllib_request
import config
import logging
-import urlparse
+from urllib import parse as urlparse
import tempfile
import ebooklib
import datetime
-import StringIO
+from io import StringIO, BytesIO
import importlib
from django.conf import settings
@@ -206,7 +206,7 @@ def _convert_file_name(file_name):
_ext = name[name.rfind('.'):]
name = booktype_slugify(_np) + _ext
- name = urllib.unquote(name)
+ name = urlparse.unquote(name)
name = name.replace(' ', '_')
return name
@@ -261,7 +261,7 @@ def _parse_toc(elements, parent=None):
pass
elif isinstance(_elem, epub.Link):
_u = urlparse.urlparse(_elem.href)
- _name = urllib.unquote(os.path.basename(_u.path))
+ _name = urlparse.unquote(os.path.basename(_u.path))
if not _name:
_name = _elem.title
@@ -288,7 +288,11 @@ def _parse_toc(elements, parent=None):
)
s = attach.get_content()
- f = StringIO.StringIO(s)
+ # Use BytesIO for binary data
+ if isinstance(s, bytes):
+ f = BytesIO(s)
+ else:
+ f = StringIO(s)
f2 = File(f)
f2.size = len(s)
att.attachment.save(attach.file_name, f2, save=False)
@@ -304,7 +308,7 @@ def _parse_toc(elements, parent=None):
continue
# check if this chapter name already exists
- name = urllib.unquote(os.path.basename(chap.file_name))
+ name = urlparse.unquote(os.path.basename(chap.file_name))
content = chap.get_body_content()
# maybe this part has to go to the plugin
@@ -320,7 +324,7 @@ def _parse_toc(elements, parent=None):
chapter = models.Chapter(
book=book,
version=book.version,
- url_title=booktype_slugify(unicode(name)),
+ url_title=booktype_slugify(str(name)),
title=name,
status=stat,
content=content,
@@ -328,7 +332,7 @@ def _parse_toc(elements, parent=None):
modified=now
)
chapter.save()
- _imported[urllib.unquote(os.path.basename(chap.file_name))] = chapter
+ _imported[urlparse.unquote(os.path.basename(chap.file_name))] = chapter
# fix links
for chap in epub_book.get_items_of_type(ebooklib.ITEM_DOCUMENT):
@@ -354,7 +358,7 @@ def _parse_toc(elements, parent=None):
if _href:
_u = urlparse.urlparse(_href)
- pth = urllib.unquote(os.path.basename(_u.path))
+ pth = urlparse.unquote(os.path.basename(_u.path))
if pth in _imported:
_name = _imported[pth].url_title
@@ -365,8 +369,8 @@ def _parse_toc(elements, parent=None):
if to_save:
chap.content = etree.tostring(tree, pretty_print=True, encoding='utf-8', xml_declaration=True)
- _imported[urllib.unquote(os.path.basename(chap.file_name))].content = chap.content
- _imported[urllib.unquote(os.path.basename(chap.file_name))].save()
+ _imported[urlparse.unquote(os.path.basename(chap.file_name))].content = chap.content
+ _imported[urlparse.unquote(os.path.basename(chap.file_name))].save()
n = len(toc) + 1
parents = {}
diff --git a/lib/booktype/utils/permissions.py b/lib/booktype/utils/permissions.py
index 8c0a0daa4..aef859fbd 100644
--- a/lib/booktype/utils/permissions.py
+++ b/lib/booktype/utils/permissions.py
@@ -24,19 +24,19 @@ def create_permissions(app_name, app_perms, stdout=True):
if len(permissions) > 0:
if stdout:
- print "Updating permissions for %s" % app_name
+ print("Updating permissions for %s" % app_name)
for codename, description in permissions:
perm, _ = Permission.objects.get_or_create(
app_name=perms_app_name,
name=codename
)
- perm.description = unicode(description)
+ perm.description = str(description)
perm.save()
created_perms.append(perm)
if stdout:
- print "\t- saving %s.%s permission".expandtabs(4) \
- % (perms_app_name, codename)
+ print("\t- saving %s.%s permission".expandtabs(4)
+ % (perms_app_name, codename))
return created_perms
diff --git a/lib/booktype/utils/tidy.py b/lib/booktype/utils/tidy.py
index 0a8693c91..709e1d297 100644
--- a/lib/booktype/utils/tidy.py
+++ b/lib/booktype/utils/tidy.py
@@ -41,7 +41,7 @@ def tidy_cleanup(content, **extra):
content = misc.remove_unknown_tags(content)
- for k, v in extra.iteritems():
+ for k, v in extra.items():
cmd.append('--%s' % k)
if v:
diff --git a/lib/booktype/utils/wordcount.py b/lib/booktype/utils/wordcount.py
index 64623eedd..202ebd853 100644
--- a/lib/booktype/utils/wordcount.py
+++ b/lib/booktype/utils/wordcount.py
@@ -50,14 +50,14 @@ def _wordcount(i):
def wordcount(text):
- if isinstance(text, str):
- text = unicode(text, "utf-8")
+ if isinstance(text, bytes):
+ text = text.decode('utf-8')
return _wordcount(iter(text))
def charcount(text):
- if isinstance(text, str):
- text = unicode(text, "utf-8")
+ if isinstance(text, bytes):
+ text = text.decode('utf-8')
count = 0
try:
i = iter(text)
@@ -70,8 +70,8 @@ def charcount(text):
def charspacecount(text):
- if isinstance(text, str):
- text = unicode(text, "utf-8")
+ if isinstance(text, bytes):
+ text = text.decode('utf-8')
count = 0
try:
i = iter(text)
@@ -83,11 +83,11 @@ def charspacecount(text):
if __name__ == "__main__":
- print wordcount("")
- print wordcount(" ")
- print wordcount(" a")
- print wordcount(" ,., ....")
- print wordcount(" a b ,., ....")
- print wordcount(" a b ,., .... c ")
- print wordcount(",,, 1 2 3 4 5 6 7 8 9 deset ,,,.. jedanaest")
- print charspacecount("ab cd")
+ print(wordcount(""))
+ print(wordcount(" "))
+ print(wordcount(" a"))
+ print(wordcount(" ,., ...."))
+ print(wordcount(" a b ,., ...."))
+ print(wordcount(" a b ,., .... c "))
+ print(wordcount(",,, 1 2 3 4 5 6 7 8 9 deset ,,,.. jedanaest"))
+ print(charspacecount("ab cd"))
diff --git a/lib/booktypecontrol/forms.py b/lib/booktypecontrol/forms.py
index e54c422e5..f0273616a 100644
--- a/lib/booktypecontrol/forms.py
+++ b/lib/booktypecontrol/forms.py
@@ -132,9 +132,8 @@ class AppearanceForm(BaseControlForm, forms.Form):
@classmethod
def initial_data(cls):
try:
- f = open('%s/css/_user.css' % settings.STATIC_ROOT, 'r')
- css_content = unicode(f.read(), 'utf8')
- f.close()
+ with open('%s/css/_user.css' % settings.STATIC_ROOT, 'r', encoding='utf-8') as f:
+ css_content = f.read()
except IOError:
css_content = ''
@@ -190,9 +189,10 @@ def initial_data(cls):
f = open(
'%s/templates/portal/welcome_message.html'
% settings.BOOKTYPE_ROOT,
- 'r'
+ 'r',
+ encoding='utf-8'
)
- _dict['description'] = unicode(f.read(), 'utf8')
+ _dict['description'] = f.read()
f.close()
except IOError:
_dict['description'] = ''
diff --git a/lib/booktypecontrol/migrations/0002_static_user_css.py b/lib/booktypecontrol/migrations/0002_static_user_css.py
index 2e2e2daac..94f412906 100644
--- a/lib/booktypecontrol/migrations/0002_static_user_css.py
+++ b/lib/booktypecontrol/migrations/0002_static_user_css.py
@@ -13,14 +13,14 @@ def create_user_css(apps, schema_editor):
try:
os.mkdir('%s/css/' % settings.STATIC_ROOT)
except OSError as err:
- print err
+ print(err)
raise RuntimeError('Can not create css directory.')
f = open('%s/css/_user.css' % settings.STATIC_ROOT, 'w')
f.write(' ')
f.close()
except IOError as err:
- print err
+ print(err)
raise RuntimeError('Can not create the file.')
diff --git a/lib/booktypecontrol/views.py b/lib/booktypecontrol/views.py
index a6f2bcc1f..e3f7952cc 100644
--- a/lib/booktypecontrol/views.py
+++ b/lib/booktypecontrol/views.py
@@ -222,7 +222,7 @@ def form_valid(self, form):
form.success_message or _('Successfully saved settings.')
)
except Exception as err:
- print err
+ print(err)
messages.warning(self.request,
_('Unknown error while saving changes.'))
return super(ControlCenterSettings, self).form_valid(form)
@@ -473,7 +473,7 @@ def delete(self, request, *args, **kwargs):
try:
group.remove_group_images()
except Exception as e:
- print e
+ print(e)
return super(DeleteGroupView, self).delete(request, *args, **kwargs)
diff --git a/lib/sputnik/redis-backuo.py b/lib/sputnik/redis-backuo.py
index fee9f985e..212e3d44e 100755
--- a/lib/sputnik/redis-backuo.py
+++ b/lib/sputnik/redis-backuo.py
@@ -92,7 +92,7 @@ def _encode(self, s):
if isinstance(s, unicode):
try:
return s.encode(self.charset, self.errors)
- except UnicodeEncodeError, e:
+ except UnicodeEncodeError as e:
raise InvalidData("Error encoding unicode value '%s': %s" % (value.encode(self.charset, 'replace'), e))
return str(s)
@@ -103,7 +103,7 @@ def _send_command(self, s):
>>> r._sock.close()
>>> try:
... r._send_command('pippo')
- ... except ConnectionError, e:
+ ... except ConnectionError as e:
... print e
Error 9 while writing to socket. Bad file descriptor.
>>>
@@ -114,7 +114,7 @@ def _send_command(self, s):
try:
self._sock.sendall(s)
- except socket.error, e:
+ except socket.error as e:
self.lck.release()
if e.args[0] == 32:
# broken pipe
@@ -137,7 +137,7 @@ def _send_command_retry(self, s):
def _read(self):
try:
return self._fp.readline()
- except socket.error, e:
+ except socket.error as e:
if e.args and e.args[0] == errno.EAGAIN:
return
self.disconnect()
@@ -363,14 +363,14 @@ def rename(self, src, dst, preserve=False):
>>> r = Redis(db=9)
>>> try:
... r.rename('a', 'a')
- ... except ResponseError, e:
+ ... except ResponseError as e:
... print e
source and destination objects are the same
>>> r.rename('a', 'b')
'OK'
>>> try:
... r.rename('a', 'b')
- ... except ResponseError, e:
+ ... except ResponseError as e:
... print e
no such key
>>> r.set('a', 1)
@@ -432,7 +432,7 @@ def push(self, name, value, head=False):
'OK'
>>> try:
... r.push('a', 'a')
- ... except ResponseError, e:
+ ... except ResponseError as e:
... print e
Operation against a key holding the wrong kind of value
>>>
@@ -492,7 +492,7 @@ def ltrim(self, name, start, end):
1
>>> try:
... r.ltrim('l', 0, 1)
- ... except ResponseError, e:
+ ... except ResponseError as e:
... print e
no such key
>>> r.push('l', 'aaa')
@@ -600,14 +600,14 @@ def lset(self, name, index, value):
1
>>> try:
... r.lset('l', 0, 'a')
- ... except ResponseError, e:
+ ... except ResponseError as e:
... print e
no such key
>>> r.push('l', 'aaa')
'OK'
>>> try:
... r.lset('l', 1, 'a')
- ... except ResponseError, e:
+ ... except ResponseError as e:
... print e
index out of range
>>> r.lset('l', 0, 'bbb')
@@ -699,7 +699,7 @@ def sort(self, name, by=None, get=None, start=None, num=None, desc=False, alpha=
stmt.append("LIMIT %s %s" % (start, num))
if get is None:
pass
- elif isinstance(get, basestring):
+ elif isinstance(get, str):
stmt.append("GET %s" % get)
elif isinstance(get, list) or isinstance(get, tuple):
for g in get:
@@ -827,12 +827,12 @@ def sinter(self, *args):
1
>>> try:
... r.sinter()
- ... except ResponseError, e:
+ ... except ResponseError as e:
... print e
wrong number of arguments for 'sinter' command
>>> try:
... r.sinter('l')
- ... except ResponseError, e:
+ ... except ResponseError as e:
... print e
Operation against a key holding the wrong kind of value
>>> r.sinter('s1', 's2', 's3')
@@ -876,7 +876,7 @@ def smembers(self, name):
1
>>> try:
... r.smembers('l')
- ... except ResponseError, e:
+ ... except ResponseError as e:
... print e
Operation against a key holding the wrong kind of value
>>> r.smembers('s')
@@ -1328,7 +1328,7 @@ def connect(self):
sock.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, self.nodelay)
setattr(connections, self.connection_key, sock)
sock = getattr(connections, self.connection_key)
- except socket.error, e:
+ except socket.error as e:
raise ConnectionError("Error %s connecting to %s:%s. %s." % (e.args[0], self.host, self.port, e.args[1]))
else:
# no exceptions
diff --git a/lib/sputnik/views.py b/lib/sputnik/views.py
index 3c6b7ec4a..4cd55c008 100644
--- a/lib/sputnik/views.py
+++ b/lib/sputnik/views.py
@@ -164,19 +164,19 @@ def dispatcher(request, **sputnik_dict):
# For now they all do the same thing but this might change in the future
try:
ret = fnc(request, message, **a)
- except ObjectDoesNotExist, e:
+ except ObjectDoesNotExist as e:
execute_status = False
logger.error("[{}] Object you are trying to find does not exist.".format("remote_{}".format(message.get('command', ''))))
logger.exception(e)
- except SuspiciousOperation, e:
+ except SuspiciousOperation as e:
execute_status = False
logger.error("[{}] Suspicious operation.".format("remote_{}".format(message.get('command', ''))))
logger.exception(e)
- except PermissionDenied, e:
+ except PermissionDenied as e:
execute_status = False
logger.error("[{}] Permission denied.".format("remote_{}".format(message.get('command', ''))))
logger.exception(e)
- except Exception, e:
+ except Exception as e:
execute_status = False
logger.error("[{}] Unknown exception.".format("remote_{}".format(message.get('command', ''))))
logger.exception(e)
diff --git a/requirements/_base.txt b/requirements/_base.txt
index c42c79a48..5351ca4ce 100644
--- a/requirements/_base.txt
+++ b/requirements/_base.txt
@@ -1,18 +1,18 @@
-Django>1.11.18,<2.0
-django-compressor==2.2
-celery==4.1.1
-django-celery-results==1.0.1
+Django>=2.2,<3.0
+django-compressor>=2.4
+celery>=4.4.0
+django-celery-results>=1.2.0
Unidecode
lxml
-Pillow==2.9.0
-redis==2.9.1
+Pillow>=6.0.0
+redis>=3.0.0
pika
unipath
django-braces
python-ooxml
-django-rest-swagger==2.1.0
-djangorestframework==3.5.3
-Markdown==2.6.7
-django-filter==1.1.0
-Ebooklib==0.16
-GitPython==2.1.8
+drf-yasg>=1.20.0
+djangorestframework>=3.11.0
+Markdown>=3.0.0
+django-filter>=2.2.0
+Ebooklib>=0.17
+GitPython>=3.0.0
diff --git a/requirements/dev.txt b/requirements/dev.txt
index 5e84b7df3..4c20fbcd6 100644
--- a/requirements/dev.txt
+++ b/requirements/dev.txt
@@ -1,16 +1,14 @@
-r _base.txt
-requests==2.9.2
-sqlparse==0.2.2
-django-debug-toolbar==1.6
-django-discover-runner
+requests>=2.20.0
+sqlparse>=0.3.0
+django-debug-toolbar>=2.0
mock
-selenium
+selenium>=3.141.0
factory_boy
sphinx
-pep8
-pytest==3.0.7
-pytest-cov==2.4.0
-pytest-django==3.1.2
-pytest-pythonpath==0.7.1
-Faker==0.7.10
+pytest>=5.0.0
+pytest-cov>=2.8.0
+pytest-django>=3.8.0
+pytest-pythonpath>=0.7.3
+Faker>=4.0.0
diff --git a/requirements/prod.txt b/requirements/prod.txt
index f88ba0f94..046040b94 100644
--- a/requirements/prod.txt
+++ b/requirements/prod.txt
@@ -1,6 +1,6 @@
-r _base.txt
urllib3[secure]
-requests[security]==2.9.2
+requests[security]>=2.20.0
psycopg2-binary
-BeautifulSoup
+beautifulsoup4
diff --git a/setup.py b/setup.py
index 0bb5f17c4..9036e540a 100644
--- a/setup.py
+++ b/setup.py
@@ -44,15 +44,20 @@ def read(*rnames):
},
scripts=['scripts/createbooktype'],
- install_requires=['setuptools', 'simplejson', 'django'],
+ install_requires=['setuptools', 'django'],
classifiers=[
"License :: OSI Approved :: GNU General Public License (GPL)",
"Programming Language :: Python",
+ "Programming Language :: Python :: 3",
+ "Programming Language :: Python :: 3.6",
+ "Programming Language :: Python :: 3.7",
+ "Programming Language :: Python :: 3.8",
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"Intended Audience :: Information Technology",
"Framework :: Django",
],
+ python_requires='>=3.6',
keywords='collaborative book writing sprint',
license='AGPL',