from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals

import base64
import hashlib
import hmac
import os

class ThumborService(object):

    def __init__(self, thumborBaseUrl='http://localhost:8888/', thumborKey=None):
        self.thumborBaseUrl = thumborBaseUrl if isinstance(thumborBaseUrl, unicode) else thumborBaseUrl.decode('utf-8')

        if thumborKey:
            self.thumborKey = thumborKey if isinstance(thumborKey, bytes) else thumborKey.encode('utf-8')
        else:
            self.thumborKey = None

    def generate_url(self, operations, target_url):
        op = "/".join(operations + (target_url,))
        key = base64.urlsafe_b64encode(hmac.new(self.thumborKey, op.encode('utf-8'), hashlib.sha1).digest()) if self.thumborKey else 'unsafe'
        return self.thumborBaseUrl + key + u'/' + op


class ThumborUrlGenerator(object):

    def __init__(self, service, operations=('fit-in', '320x320'), key='content_url', destkey='thumbnail'):
        self.service = service
        self.operations = operations
        self.key = key
        self.destkey = destkey

    def __call__(self, item, send):
        for oid in item['inserts']:
            item['data'][oid][self.destkey] = self.service.generate_url(self.operations, item['data'][oid][self.key])

        send(item, self)

    @property
    def dependencies(self):
        yield (self, self.service)

@@ -345,23 +345,21 @@
 aseUrl, 
-unicode
+bytes
 ) else t
@@ -376,21 +376,21 @@
 Url.
-d
 e
+n
 code('
-utf-8
+ascii
 ')%0A%0A
@@ -634,20 +634,82 @@
   op
- = %22/%22.join(
+erations = %5Bop if isinstance(op, bytes) else op.encode('ascii') for op in 
 oper
@@ -718,24 +718,179 @@
 ions
- + (target_url,)
+%5D%0A        target_url = target_url if isinstance(target_url, bytes) else target_url.encode('ascii')%0A        operations.append(target_url)%0A%0A        op = b'/'.join(operations
 )%0A  
@@ -954,32 +954,16 @@
 rKey, op
-.encode('utf-8')
 , hashli
@@ -1004,16 +1004,17 @@
 ey else 
+b
 'unsafe'
@@ -1029,16 +1029,17 @@
  return 
+(
 self.thu
@@ -1062,17 +1062,17 @@
 y + 
-u
+b
 '/' + op
 %0A%0A%0Ac
@@ -1067,16 +1067,33 @@
 '/' + op
+).decode('ascii')
 %0A%0A%0Aclass

Use byte strings internally, only accept unicode URLs operators if they only contain ASCII characters