-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
+# This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
+# Copyright © Fundacja Wolne Lektury. See NOTICE for more information.
+#
 from operator import and_
-
+import functools
+import io
 from .dcparser import Field, WorkInfo, DCNS
 from librarian import (RDFNS, ValidationError, NoDublinCore, ParseError, WLURI)
 from xml.parsers.expat import ExpatError
 from lxml import etree
 from lxml.etree import (XMLSyntaxError, XSLTApplyError, Element)
 import re
-import six
 
 
 class WLPictureURI(WLURI):
     _re_wl_uri = re.compile(
         'http://wolnelektury.pl/katalog/obraz/(?P<slug>[-a-z0-9]+)/?$'
     )
-
-    @classmethod
-    def from_slug(cls, slug):
-        uri = 'http://wolnelektury.pl/katalog/obraz/%s/' % slug
-        return cls(uri)
+    template = 'http://wolnelektury.pl/katalog/obraz/%s/'
 
 
 def as_wlpictureuri_strict(text):
     )
 
 
-class ImageStore(object):
+class ImageStore:
     EXT = ['gif', 'jpeg', 'png', 'swf', 'psd', 'bmp'
            'tiff', 'tiff', 'jpc', 'jp2', 'jpf', 'jb2', 'swc',
            'aiff', 'wbmp', 'xbm']
         return path.join(self.dir, slug + '.' + ext)
 
 
-class WLPicture(object):
+class WLPicture:
     def __init__(self, edoc, parse_dublincore=True, image_store=None):
         self.edoc = edoc
         self.image_store = image_store
 
     @classmethod
     def from_bytes(cls, xml, *args, **kwargs):
-        return cls.from_file(six.BytesIO(xml), *args, **kwargs)
+        return cls.from_file(io.BytesIO(xml), *args, **kwargs)
 
     @classmethod
     def from_file(cls, xmlfile, parse_dublincore=True, image_store=None):
 
         # first, prepare for parsing
-        if isinstance(xmlfile, six.text_type):
+        if isinstance(xmlfile, str):
             file = open(xmlfile, 'rb')
             try:
                 data = file.read()
         else:
             data = xmlfile.read()
 
-        if not isinstance(data, six.text_type):
+        if not isinstance(data, str):
             data = data.decode('utf-8')
 
-        data = data.replace(u'\ufeff', '')
+        data = data.replace('\ufeff', '')
 
         # assume images are in the same directory
         if image_store is None and getattr(xmlfile, 'name', None):
 
         try:
             parser = etree.XMLParser(remove_blank_text=False)
-            tree = etree.parse(six.BytesIO(data.encode('utf-8')), parser)
+            tree = etree.parse(io.BytesIO(data.encode('utf-8')), parser)
 
             me = cls(tree, parse_dublincore=parse_dublincore,
                      image_store=image_store)
             return [[0, 0], [-1, -1]]
 
         def has_all_props(node, props):
-            return reduce(and_, map(lambda prop: prop in node.attrib, props))
+            return functools.reduce(
+                and_, map(lambda prop: prop in node.attrib, props)
+            )
 
         if not has_all_props(area, ['x1', 'x2', 'y1', 'y2']):
             return None
             pd['coords'] = coords
 
             def want_unicode(x):
-                if not isinstance(x, six.text_type):
+                if not isinstance(x, str):
                     return x.decode('utf-8')
                 else:
                     return x
             pd['object'] = (
                 part.attrib['type'] == 'object'
-                and want_unicode(part.attrib.get('object', u''))
+                and want_unicode(part.attrib.get('object', ''))
                 or None
             )
             pd['themes'] = (
                 part.attrib['type'] == 'theme'
-                and [part.attrib.get('theme', u'')]
+                and [part.attrib.get('theme', '')]
                 or []
             )
             yield pd
             clip = self.get_sem_coords(k)
             self.frame = clip
             frm = Element("sem", {"type": "frame"})
-            frm.append(k.iter("div").next())
+            frm.append(next(k.iter("div")))
             self.edoc.getroot().append(frm)
             k.getparent().remove(k)
         else: