Exemple #1
0
def process_image(self, image_contents_id):
    session = Client().session()
    contents = session.query(ImageContents).\
        filter(ImageContents.image_contents_id == image_contents_id).\
        one()

    image = session.query(Image).\
        filter(Image.image_id == contents.image_id).\
        one()

    truck = ImageTruck(
        contents.contents, contents.content_type, image.source_url)
    truck.filename = image.filename
    metadata = ImageMetadata.image_metadata(truck.contents)
    truck.contents = ReorientImage.reorient_image(truck.contents)
    def after_upload(size):
        redis.publish(REDIS_CHANNEL, json.dumps({
            'task_id': self.request.id,
            'suffix': size,
        }))
    ResizeImage.make_resizes(image, truck, after_upload)

    print "uploading original image"
    truck.upload()
    redis.publish(REDIS_CHANNEL, json.dumps({
        'task_id': self.request.id,
        'suffix': '',
    }))

    delay(queued_tasks, Invalidate(), image.image_id)

    for attr, value in metadata.iteritems():
        setattr(image, attr, value)
    session.add(image)
    session.delete(contents)
Exemple #2
0
def add(request_format):
    tag_names = request.form['tags'].split(' ')
    url = request.form['url']

    if url:
        print 'fetching from remote url'
        truck = ImageTruck.new_from_url(url)
    elif request.files['file']:
        image = request.files['file']
        truck = ImageTruck.new_from_stream(image.stream, image.mimetype)
    else:
        abort(400)
    metadata = ImageMetadata.image_metadata(truck.contents)
    print 'potentially reorienting'
    truck.contents = ReorientImage.reorient_image(truck.contents)
    print 'uploading to s3'
    truck.upload()
    session = Client().session()
    image = Image(filename=truck.calculate_filename(),
                  source_url=url,
                  description=request.form.get('description'),
                  title=request.form.get('title'),
                  **metadata)
    album_id = request.form['album']
    if album_id:
        image.album_id = album_id
    session.add(image)
    image.add_tags(tag_names)

    ResizeImage.make_resizes(image, truck)

    if request_format == 'html':
        return redirect(url_for('show_image', image_id=image.image_id))
    elif request_format == 'json':
        return {'url': truck.url()}
Exemple #3
0
    def test_url_for_filename__with_extension(self, _url, Config):
        config = Mock()
        config.bucket_name.return_value = 'greeble'
        Config.return_value = config

        ImageTruck.url_for_filename('CAFEBABE', extension=True)
        _url.assert_called_once_with('CAFEBABE', 'greeble', extension=True)
 def test_calculate_filename(self, hashlib):
     sha = Mock()
     sha.hexdigest.return_value = 'indigestible'
     hashlib.sha1.return_value = sha
     truck = ImageTruck('razors', None, None)
     eq_(truck.calculate_filename(), 'indigestible')
     hashlib.sha1.assert_called_with('razors')
Exemple #5
0
def add(request_format):
    url = request.form.get("url")

    if url:
        try:
            trucks = [ImageTruck.new_from_url(url)]
        except RequestException:
            abort(request_format, 400, "That url is no good.")
        except TryHTTPError:
            abort(
                request_format,
                400,
                "Catsnap couldn't establish an HTTPS connection to that "
                "image. An HTTP connection may succeed (this is a problem "
                "on Catsnap's end, not something you did wrong).",
            )
    elif request.files.get("file[]"):
        trucks = [ImageTruck.new_from_stream(data.stream) for data in request.files.getlist("file[]")]
    elif request.files.get("file"):
        data = request.files["file"]
        trucks = [ImageTruck.new_from_stream(data.stream)]
    else:
        abort(request_format, 400, "Please submit either a file or a url.")

    # These loops are sorta awkwardly phrased to avoid lots of round-tripping
    # to the database. I hope you don't consider the optimization premature.
    session = Client().session()
    images = []
    for truck in trucks:
        image = Image(filename=truck.filename, source_url=url)
        album_id = request.form.get("album_id")
        if album_id:
            image.album_id = int(album_id)
        session.add(image)
        images.append(image)

    session.flush()
    contentses = []
    for i in xrange(0, len(images)):
        (truck, image) = trucks[i], images[i]
        contents = ImageContents(image_id=image.image_id, contents=truck.contents, content_type=truck.content_type)
        session.add(contents)
        contentses.append(contents)
    session.flush()

    task_ids = []
    # Hey, this is a loop around a round-trip to redis. Although the Python
    # Redis library offers a way to send multiple requests in one thwack,
    # Celery doesn't appear to offer a way to use it. Nothing to be done.
    for contents in contentses:
        task_ids.append(delay(g.queued_tasks, process_image, contents.image_contents_id))

    if request_format == "html":
        return redirect(url_for("show_image", image_id=image.image_id))
    elif request_format == "json":
        return [
            {"url": trucks[i].url(), "image_id": images[i].image_id, "task_id": task_ids[i]}
            for i in xrange(0, len(trucks))
        ]
    def test_get_contents_of_nonexistent_filename(self, MockClient):
        bucket = Mock()
        bucket.get_key.return_value = None
        client = Mock()
        client.bucket.return_value = bucket
        MockClient.return_value = client

        ImageTruck.contents_of_filename('x')
Exemple #7
0
    def test_url(self, calculate_filename, Config):
        config = Mock()
        config.bucket_name.return_value = 'tune-carrier'
        Config.return_value = config
        calculate_filename.return_value = 'greensleeves'

        truck = ImageTruck('greensleeves', None, None)
        eq_(truck.url(), 'https://s3.amazonaws.com/tune-carrier/greensleeves')
Exemple #8
0
    def test_new_from_url_reraises_non_sni_ssl_errors(self, mock_requests):
        error = requests.exceptions.SSLError(
            urllib3.exceptions.SSLError(
                CertificateError("hostname 'catsinthecity.com' doesn't "
                                 "match 'nossl.edgecastcdn.net'")))

        mock_requests.get.side_effect = error

        ImageTruck.new_from_url('https://catsinthecity.com/image.jpg')
Exemple #9
0
def add(request_format):
    url = request.form.get('url')

    if url:
        try:
            trucks = [ImageTruck.new_from_url(url)]
        except RequestException:
            abort(request_format, 400, "That url is no good.")
    elif request.files.get('file[]'):
        trucks = [ImageTruck.new_from_stream(data.stream)
                  for data in request.files.getlist('file[]')]
    elif request.files.get('file'):
        data = request.files['file']
        trucks = [ImageTruck.new_from_stream(data.stream)]
    else:
        abort(request_format, 400, "Please submit either a file or a url.")

    # These loops are sorta awkwardly phrased to avoid lots of round-tripping
    # to the database. I hope you don't consider the optimization premature.
    session = Client().session()
    images = []
    for truck in trucks:
        image = Image(filename=truck.filename, source_url=url)
        album_id = request.form.get('album_id')
        if album_id:
            image.album_id = int(album_id)
        session.add(image)
        images.append(image)

    session.flush()
    contentses = []
    for i in xrange(0, len(images)):
        (truck, image) = trucks[i], images[i]
        contents = ImageContents(image_id=image.image_id,
                                 contents=truck.contents,
                                 content_type=truck.content_type)
        session.add(contents)
        contentses.append(contents)
    session.flush()

    task_ids = []
    # Hey, this is a loop around a round-trip to redis. Although the Python
    # Redis library offers a way to send multiple requests in one thwack,
    # Celery doesn't appear to offer a way to use it. Nothing to be done.
    for contents in contentses:
        task_ids.append(delay(g.queued_tasks,
                              process_image,
                              contents.image_contents_id))

    if request_format == 'html':
        return redirect(url_for('show_image', image_id=image.image_id))
    elif request_format == 'json':
        return [{
                'url': trucks[i].url(),
                'image_id': images[i].image_id,
                'task_id': task_ids[i],
            } for i in xrange(0, len(trucks))]
Exemple #10
0
    def test_new_from_url_raises_usefully_for_sni_trouble(self, mock_requests):
        error = requests.exceptions.SSLError(
            urllib3.exceptions.SSLError(
                ssl.SSLError(1, '_ssl.c:503: error:14077410:SSL routines:'
                                'SSL23_GET_SERVER_HELLO:sslv3 alert handshake '
                                'failure')))

        mock_requests.get.side_effect = error

        ImageTruck.new_from_url('https://some.server.using.sni/image.jpg')
Exemple #11
0
    def test_url__with_extension(self, calculate_filename, Config, _url):
        config = Mock()
        config.bucket_name.return_value = 'tune-carrier'
        Config.return_value = config
        calculate_filename.return_value = 'greensleeves'
        truck = ImageTruck('greensleeves', None, None)

        truck.url(extension=True)
        _url.assert_called_once_with('greensleeves', 'tune-carrier',
                extension=True)
Exemple #12
0
    def test_get_bucket_creates_bucket_connection(self, Config):
        config = Mock()
        Config.return_value = config
        mock_bucket = Mock()
        truck = ImageTruck(None, None, None)
        truck._stored_bucket = mock_bucket

        bucket = truck._bucket()
        eq_(bucket, mock_bucket)
        eq_(config.table.call_count, 0)
Exemple #13
0
    def test_get_bucket_creates_bucket_connection(self, Config):
        config = Mock()
        Config.return_value = config
        mock_bucket = Mock()
        config.bucket.return_value = mock_bucket

        truck = ImageTruck(None, None, None)
        bucket = truck._bucket()
        eq_(bucket, mock_bucket)
        eq_(truck._stored_bucket, mock_bucket)
        config.bucket.assert_called_with()
Exemple #14
0
    def test_url__with_cloudfront_url(self, calculate_filename, MockClient):
        client = Mock()
        client.cloudfront_url.return_value = \
            'ggaaghlhaagl.cloudfront.net'
        client.config.return_value = Client().config()
        MockClient.return_value = client

        calculate_filename.return_value = 'chumbawamba'
        truck = ImageTruck('tubthumper', None, None)

        url = truck.url()
        eq_(url, 'https://ggaaghlhaagl.cloudfront.net/chumbawamba')
        client.cloudfront_url.assert_called_with('JEEZAMANDA')
Exemple #15
0
    def test_save__uploads_image(self, calculate_filename):
        bucket = Mock()
        key = Mock()
        bucket.new_key.return_value = key
        calculate_filename.return_value = 'I am the keymaster'

        truck = ImageTruck('Are you the gatekeeper?', 'image/gif', None)
        truck._stored_bucket = bucket
        truck.upload()

        bucket.new_key.assert_called_with('I am the keymaster')
        key.set_contents_from_string.assert_called_with(
                'Are you the gatekeeper?')
        key.set_metadata.assert_called_with('Content-Type', 'image/gif')
        key.make_public.assert_called_with()
    def test_upload_resize(self, calculate_filename, MockClient):
        bucket = Mock()
        key = Mock()
        bucket.new_key.return_value = key
        client = Mock()
        client.bucket.return_value = bucket
        MockClient.return_value = client
        calculate_filename.return_value = 'faceb00c'

        truck = ImageTruck('contentsoffile', 'image/gif', None)
        truck.upload_resize('resizedcontents', 'small')

        bucket.new_key.assert_called_with('faceb00c_small')
        key.set_contents_from_string.assert_called_with('resizedcontents')
        key.set_metadata.assert_called_with('Content-Type', 'image/gif')
        key.make_public.assert_called_once()
 def test_new_from_stream(self):
     stream = StringIO.StringIO()
     stream.write('encoded jpg file')
     stream.seek(0)
     truck = ImageTruck.new_from_stream(stream, 'image/jpg')
     eq_(truck.contents, 'encoded jpg file')
     eq_(truck.content_type, 'image/jpg')
Exemple #18
0
    def file_type_test(self,
                       bucket_method,
                       test_file,
                       content_type,
                       resized_size):
        bucket = Mock()
        bucket_method.return_value = bucket
        new_key = Mock()
        bucket.new_key.return_value = new_key
        image_handler = ImageHandler(filename=test_file)
        truck = ImageTruck.new_from_file(test_file)
        session = Client().session()
        image = ImageTable(filename='badcafe')
        session.add(image)
        session.flush()
        after_upload = Mock()

        ResizeImage._resize_image(image,
                                  image_handler,
                                  truck,
                                  'thumbnail',
                                  after_upload)

        new_key.set_metadata.assert_called_with('Content-Type', content_type)
        resized_contents = new_key.set_contents_from_string.call_args[0][0]

        image_handler = ImageHandler(blob=resized_contents)
        eq_(image_handler.size, resized_size)

        after_upload.assert_called_once_with('thumbnail')
    def file_type_test(self,
                       bucket_method,
                       test_file_name,
                       content_type,
                       resized_size):
        bucket = Mock()
        bucket_method.return_value = bucket
        new_key = Mock()
        bucket.new_key.return_value = new_key
        test_file = os.path.join(os.path.dirname(__file__), test_file_name)
        image_handler = ImageHandler.open(test_file)
        with open(test_file, 'r') as fh:
            truck = ImageTruck.new_from_stream(fh, content_type)
        session = Client().session()
        image = ImageTable(filename='badcafe')
        session.add(image)
        session.flush()

        ResizeImage._resize_image(image, image_handler, truck, 'thumbnail')

        new_key.set_metadata.assert_called_with('Content-Type', content_type)
        resized_contents = new_key.set_contents_from_string.call_args[0][0]

        image_handler = ImageHandler.open(StringIO.StringIO(resized_contents))
        eq_(image_handler.size, resized_size)
    def test_new_from_url(self, requests):
        response = Mock()
        response.content = "Ain't no party like a Liz Lemon party"
        response.headers = {'content-type': 'party'}
        requests.get.return_value = response

        truck = ImageTruck.new_from_url('http://some.url')
        eq_(truck.contents, "Ain't no party like a Liz Lemon party")
        eq_(truck.content_type, "party")
        eq_(truck.source_url, "http://some.url")
Exemple #21
0
def show_image(request_format, image_id, size):
    session = Client().session()
    image = session.query(Image).\
        filter(Image.image_id == image_id).\
        one()
    if g.user:
        albums = session.query(Album).all()
    else:
        albums = []
    if image.album_id is not None:
        album = session.query(Album).\
            filter(Album.album_id == image.album_id).\
            one()
    else:
        album = None
    (prev, next) = image.neighbors()
    resizes = session.query(ImageResize).\
        filter(ImageResize.image_id == image_id).\
        order_by(ImageResize.width.asc()).\
        all()
    url = ImageTruck.url_for_filename(image.filename)

    if resizes and size in [r.suffix for r in resizes]:
        url = '{0}_{1}'.format(url, size)

    tags = image.get_tags()
    if request_format == 'html':
        return render_template('image.html.jinja',
                               image=image,
                               prev=prev,
                               next=next,
                               album=album,
                               albums=albums,
                               url=url,
                               tags=list(tags),
                               metadata_fields=filter(lambda (x,_): getattr(image, x), Image.metadata_fields),
                               getattr=getattr,
                               resizes=resizes,
                               size=size)
    elif request_format == 'json':
        return {
            'description': image.description,
            'title': image.title,
            'camera': image.camera,
            'photographed_at': image.photographed_at,
            'focal_length': image.focal_length,
            'aperture': image.aperture,
            'shutter_speed': image.shutter_speed,
            'iso': image.iso,
            'album_id': image.album_id,
            'tags': list(tags),
            'source_url': url,
        }
    def test_get_contents_of_filename(self, MockClient):
        key = Mock()
        key.get_contents_as_string.return_value = 'cow innards'
        bucket = Mock()
        bucket.get_key.return_value = key
        client = Mock()
        client.bucket.return_value = bucket
        MockClient.return_value = client

        contents = ImageTruck.contents_of_filename('deadbeef')
        eq_(contents, 'cow innards')

        bucket.get_key.assert_called_with('deadbeef')
    def test_new_from_file(self, subprocess):
        subprocess.check_output.return_value = \
                'space-centurion.png: PNG image data, 1280 x 800, ' \
                '8-bit/color RGB, non-interlaced'
        (_, image) = tempfile.mkstemp()
        with open(image, 'w') as image_file:
            image_file.write('here are some contents')

        truck = ImageTruck.new_from_file(image)
        eq_(truck.content_type, "image/png")
        eq_(truck.contents, 'here are some contents')
        eq_(truck.source_url, None)
        subprocess.check_output.assert_called_with(['file', image])
Exemple #24
0
def show_image(request_format, image_id, size):
    session = Client().session()
    image = session.query(Image).filter(Image.image_id == image_id).one()
    if g.user:
        albums = session.query(Album).all()
    else:
        albums = []
    if image.album_id is not None:
        album = session.query(Album).filter(Album.album_id == image.album_id).one()
    else:
        album = None
    (prev, next) = image.neighbors()
    resizes = (
        session.query(ImageResize).filter(ImageResize.image_id == image_id).order_by(ImageResize.width.asc()).all()
    )
    url = ImageTruck.url_for_filename(image.filename)

    if resizes and size in [r.suffix for r in resizes]:
        url = "{0}_{1}".format(url, size)

    tags = image.get_tags()
    if request_format == "html":
        return render_template(
            "image.html.jinja",
            image=image,
            prev=prev,
            next=next,
            album=album,
            albums=albums,
            url=url,
            tags=list(tags),
            metadata_fields=filter(lambda (x, _): getattr(image, x), Image.metadata_fields),
            getattr=getattr,
            resizes=resizes,
            size=size,
        )
    elif request_format == "json":
        return {
            "description": image.description,
            "title": image.title,
            "camera": image.camera,
            "photographed_at": image.photographed_at,
            "focal_length": image.focal_length,
            "aperture": image.aperture,
            "shutter_speed": image.shutter_speed,
            "iso": image.iso,
            "album_id": image.album_id,
            "tags": list(tags),
            "source_url": url,
        }
Exemple #25
0
def find(request_format):
    tag_names = request.args['tags'].strip().split(' ')
    image_structs = []
    image_data = Tag.get_image_data(tag_names)
    for filename, image_id, caption in image_data:
        image_structs.append({
            'source_url': ImageTruck.url_for_filename(filename),
            'url': url_for('show_image', image_id=image_id),
            'caption': caption,
        })
    if request_format == 'html':
        return render_template('find.html.jinja', images=image_structs)
    elif request_format == 'json':
        return image_structs
Exemple #26
0
def reprocess_image(request_format, image_id):
    session = Client().session()
    image = session.query(Image).filter(Image.image_id == image_id).one()

    truck = ImageTruck.new_from_image(image)
    contents = ImageContents(image_id=image.image_id, contents=truck.contents, content_type=truck.content_type)

    session.add(contents)
    session.flush()
    delay(g.queued_tasks, process_image, contents.image_contents_id)

    if request_format == "json":
        return {"status": "ok"}
    else:
        return redirect(url_for("show_image", image_id=image.image_id))
Exemple #27
0
def show_image(request_format, image_id, size):
    session = Client().session()
    image = session.query(Image).\
        filter(Image.image_id == image_id).\
        one()
    if g.user:
        albums = session.query(Album).all()
    else:
        albums = []
    try:
        album = filter(lambda a: a.album_id == image.album_id, albums)[0]
    except IndexError:
        album = None
    resizes = session.query(ImageResize).\
        filter(ImageResize.image_id == image_id).\
        order_by(ImageResize.width.asc()).\
        all()
    url = ImageTruck.url_for_filename(image.filename)
    if resizes and size != 'original':
        if size not in map(lambda r: r.suffix, resizes):
            size = resizes[0].suffix
        url = '%s_%s' % (url, size)
    tags = image.get_tags()
    if request_format == 'html':
        return render_template('image.html.jinja',
                               image=image,
                               album=album,
                               albums=albums,
                               url=url,
                               tags=tags,
                               resizes=resizes,
                               user=g.user,
                               size=size)
    elif request_format == 'json':
        return {
            'description': image.description,
            'title': image.title,
            'camera': image.camera,
            'photographed_at': image.photographed_at,
            'focal_length': image.focal_length,
            'aperture': image.aperture,
            'shutter_speed': image.shutter_speed,
            'iso': image.iso,
            'album_id': image.album_id,
            'tags': list(tags),
            'source_url': url,
        }
Exemple #28
0
    def test_new_from_image(self, subprocess, MockClient):
        subprocess.check_output.return_value = \
                'space-centurion.png: PNG image data, 1280 x 800, ' \
                '8-bit/color RGB, non-interlaced'

        def get_contents_to_filename(filename):
            with open(filename, 'w') as fh:
                fh.write('brain, skull, etc')
        key = Mock()
        key.get_contents_to_filename.side_effect = get_contents_to_filename
        bucket = Mock()
        bucket.get_key.return_value = key
        client = Mock()
        client.bucket.return_value = bucket
        MockClient.return_value = client

        image = Image(filename='faceface')
        truck = ImageTruck.new_from_image(image)
        eq_(truck.contents, 'brain, skull, etc')

        bucket.get_key.assert_called_with('faceface')
 def test_new_from_file__raises_well_for_non_image_files(self):
     try:
         truck = ImageTruck.new_from_file(__file__)
     except Exception, e:
         eq_(e.message, "'%s' doesn't seem to be an image file" % __file__)
         eq_(type(e), TypeError)
    def test_new_from_url__raises_on_non_200(self, requests):
        response = Mock()
        response.raise_for_status.side_effect = HTTPError
        requests.get.return_value = response

        ImageTruck.new_from_url('http://some.url')