def test_upload_item_images_post_uuid_failed(self): """ Test posting images for an item via uuid with invalid image fails. """ self._create_item_status() item = Item(name='iPhone', type='TRADE', quantity=1, description='A smart phone', status=self.draft_status, reason='just because') DBSession.add(item) DBSession.commit() class DumbMockImage(object): file = StringIO('image') filename = 'image1.jpg' item_uuid = str(uuid.uuid4()) mock_image = DumbMockImage() payload = {"uuid": item_uuid, "image": mock_image} request = testing.DummyRequest(post=payload) request.registry = self.config.registry # set a dummy uuid to regis self.redis.hset('item_uuid_to_id', item_uuid, item.id) self.redis.expire(item_uuid, 3600) self.assertRaises(HTTPBadRequest, upload_item_images, request)
def test_upload_item_images_post_id(self): """ Test posting images for an item via id. """ self._create_item_status() item = Item(name='iPhone', type='TRADE', quantity=1, description='A smart phone', status=self.draft_status, reason='just because') DBSession.add(item) DBSession.commit() uuid_filename = str(uuid.uuid4()) mock_image = MockFileImage('image1.png') # write to disk the dummy image so the view can resize it original = '%s.png' % uuid_filename static_path = pkgr.resource_filename('tradeorsale', 'static') image_path = os.path.join(static_path, os.path.join('items/images', str(item.id)), original) with open(image_path, 'wb') as handle: handle.write(mock_image.file.read()) self.failUnless(os.path.exists(image_path)) # build request mock_image.file.seek(0) payload = {"item_id": item.id, "image": mock_image} request = testing.DummyRequest(post=payload) request.registry = self.config.registry response = upload_item_images(request) self.assertEqual(response.status_code, 200) # test that there are 3 images: original, small and medium self.assertEqual(DBSession.query(ItemImage).filter_by(item_id=item.id).count(), 3)
def test_dashboard_view_drafts_nonempty(self): """ Test that dashboard view returns non-empty list draft items when there are draft items. """ self._create_item_status() DBSession.add( Item(name='iPhone', type='TRADE', description='A smart phone.', status=self.draft_status, quantity=1)) DBSession.add( Item(name='Macbook Pro', type='SALE', description='An apple product.', price=30500, status=self.ongoing_status, quantity=5)) DBSession.commit() request = testing.DummyRequest() response = dashboard(request) draft_items = json.loads(response['draft_items']) self.assertEqual(len(draft_items), 1) self.assertNotEqual(draft_items, [])
def test_upload_item_images_post_uuid_failed(self): """ Test posting images for an item via uuid with invalid image fails. """ self._create_item_status() item = Item(name='iPhone', type='TRADE', quantity=1, description='A smart phone', status=self.draft_status, reason='just because') DBSession.add(item) DBSession.commit() class DumbMockImage(object): file = StringIO('image') filename = 'image1.jpg' item_uuid = str(uuid.uuid4()) mock_image = DumbMockImage() payload = {"uuid": item_uuid, "image": mock_image} request = testing.DummyRequest(post=payload) request.registry = self.config.registry # set a dummy uuid to regis self.redis.hset('item_uuid_to_id', item_uuid, item.id) self.redis.expire(item_uuid, 3600) self.assertRaises(HTTPBadRequest, upload_item_images, request)
def delete(self): item_id = int(self.request.matchdict['item_id']) item = DBSession.query(Item).filter_by(id=item_id).one() logger.info("deleting item: %s" % item_id) item.is_deleted = True DBSession.add(item) DBSession.commit() return {'status': 'success', 'message': _(u'Item deletion successful')}
def test_create_image_path(self): """ Test that creating an item creates image path. """ self._create_item_status() item = Item(name='iPhone', type='TRADE', quantity=1, description='A smart phone', status=self.draft_status, reason='just because') DBSession.add(item) DBSession.commit() # check that the images path has been created images_path = pkgr.resource_filename('tradeorsale', 'static') item_images_abspath = os.path.join( images_path, os.path.join('items/images', str(item.id))) self.failUnless(os.path.exists(item_images_abspath))
def test_upload_item_images_post_uuid(self): """ Test posting images for an item via uuid. """ self._create_item_status() item = Item(name='iPhone', type='TRADE', quantity=1, description='A smart phone', status=self.draft_status, reason='just because') DBSession.add(item) DBSession.commit() item_uuid = str(uuid.uuid4()) mock_image = MockFileImage('image1.png') # write to disk the dummy image so the view can resize it original = '%s.png' % item_uuid static_path = pkgr.resource_filename('tradeorsale', 'static') image_path = os.path.join(static_path, os.path.join('items/images', str(item.id)), original) with open(image_path, 'wb') as handle: handle.write(mock_image.file.read()) self.failUnless(os.path.exists(image_path)) # build request mock_image.file.seek(0) payload = {"uuid": item_uuid, "image": mock_image} request = testing.DummyRequest(post=payload) request.registry = self.config.registry # set a dummy uuid to regis self.redis.hset('item_uuid_to_id', item_uuid, item.id) self.redis.expire(item_uuid, 3600) response = upload_item_images(request) self.assertEqual(response.status_code, 200) # test that there are 3 images: original, small and medium self.assertEqual( DBSession.query(ItemImage).filter_by(item_id=item.id).count(), 3)
def test_dashboard_view_drafts_nonempty(self): """ Test that dashboard view returns non-empty list draft items when there are draft items. """ self._create_item_status() DBSession.add(Item(name='iPhone', type='TRADE', description='A smart phone.', status=self.draft_status, quantity=1)) DBSession.add(Item(name='Macbook Pro', type='SALE', description='An apple product.', price=30500, status=self.ongoing_status, quantity=5)) DBSession.commit() request = testing.DummyRequest() response = dashboard(request) draft_items = json.loads(response['draft_items']) self.assertEqual(len(draft_items), 1) self.assertNotEqual(draft_items, [])
def test_item_image_delete(self): """ Test that image is deleted when DELETE request is sent. """ self._create_item_status() item = Item(name='iPhone', type='TRADE', quantity=1, description='A smart phone', status=self.draft_status, reason='just because') DBSession.add(item) DBSession.commit() # write to disk the dummy image mock_image = MockFileImage('original.jpg') static_path = pkgr.resource_filename('tradeorsale', 'static') item_images_path = os.path.join( static_path, os.path.join('items/images', str(item.id))) image_path = os.path.join(item_images_path, mock_image.filename) with open(image_path, 'wb') as handle: handle.write(mock_image.file.read()) self.failUnless(os.path.exists(image_path)) # save the image in db item_image = ItemImage( item.id, mock_image.filename, os.path.join('/%s' % item_images_path, mock_image.filename)) DBSession.add(item_image) DBSession.commit() # send DELETE request request = Request({}, method='DELETE') request.matchdict = {'id': item.id} request.registry = self.config.registry # check that record was deleted response = item_images(None, request) self.assertEqual(response.status_code, 200) self.assertEqual(DBSession.query(ItemImage).count(), 0) self.failUnless(not os.path.exists(image_path))
def test_item_image_delete(self): """ Test that image is deleted when DELETE request is sent. """ self._create_item_status() item = Item(name='iPhone', type='TRADE', quantity=1, description='A smart phone', status=self.draft_status, reason='just because') DBSession.add(item) DBSession.commit() # write to disk the dummy image mock_image = MockFileImage('original.jpg') static_path = pkgr.resource_filename('tradeorsale', 'static') item_images_path = os.path.join(static_path, os.path.join('items/images', str(item.id))) image_path = os.path.join(item_images_path, mock_image.filename) with open(image_path, 'wb') as handle: handle.write(mock_image.file.read()) self.failUnless(os.path.exists(image_path)) # save the image in db item_image = ItemImage(item.id, mock_image.filename, os.path.join('/%s' % item_images_path, mock_image.filename)) DBSession.add(item_image) DBSession.commit() # send DELETE request request = Request({}, method='DELETE') request.matchdict = {'id': item.id} request.registry = self.config.registry # check that record was deleted response = item_images(None, request) self.assertEqual(response.status_code, 200) self.assertEqual(DBSession.query(ItemImage).count(), 0) self.failUnless(not os.path.exists(image_path))
def collection_post(self): payload = MultiDict(self.request.json_body) # fetch user # TODO: assign currently logged-in user's id user = DBSession.query(User).filter_by(id=1).one() # fetch status status_name = 'DRAFTS' if payload.get('is_draft', False) else 'ONGOING' status = DBSession.query(ItemStatus).filter_by(name=status_name).one() qty = int(payload.get('quantity', 1)) price = payload['price'] if payload.get( 'price', None) and payload['price'] else None new_item = Item(user=user, name=payload['name'], type=payload['type'], trade_with=payload.get('trade_with', None), status=status, price=price, quantity=qty, description=payload['description'], reason=payload['reason']) # load assigned tags and extend new item's tags if payload.get('tags', None): tag_ids = [ tag['id'] for tag in payload['tags'] if tag.get('id', None) ] tags = DBSession.query(ItemTag).filter( ItemTag.id.in_(tag_ids)).all() new_item.tags.extend(tags) DBSession.add(new_item) DBSession.commit() return new_item.to_dict()
def test_delete_image(self): """ Test that deleting an image deletes it from disk. """ # create item first self._create_item_status() item = Item(name='iPhone', type='TRADE', quantity=1, description='A smart phone', status=self.draft_status, reason='just because') DBSession.add(item) DBSession.commit() # write to disk the dummy image mock_image = MockFileImage('original.jpg') static_path = pkgr.resource_filename('tradeorsale', 'static') item_images_path = os.path.join( static_path, os.path.join('items/images', str(item.id))) image_path = os.path.join(item_images_path, mock_image.filename) with open(image_path, 'wb') as handle: handle.write(mock_image.file.read()) self.failUnless(os.path.exists(image_path)) # save the image in db item_image = ItemImage( item.id, mock_image.filename, os.path.join('/%s' % item_images_path, mock_image.filename)) DBSession.add(item_image) DBSession.commit() # delete image and check that it doesn't exist DBSession.delete(item_image) DBSession.commit() self.failUnless(not os.path.exists(image_path))
def get(self): """ GET method for fetching single item. """ action = self.request.GET.get('action', None) item_id = int(self.request.matchdict['item_id']) item = DBSession.query(Item).filter_by(id=item_id).one() if action and action == 'clone': logger.info("cloning item: %s" % str(item_id)) draft_status = DBSession.query(ItemStatus).filter_by( name='DRAFTS').one() cloned_item = Item(user=item.user, name='%s - copy' % item.name, type=item.type, quantity=item.quantity, description=item.description, status=draft_status, price=item.price, reason=item.reason) cloned_item.tags = item.tags DBSession.add(cloned_item) DBSession.commit() # clone images static_path = pkgr.resource_filename('tradeorsale', 'static') source = os.path.join(static_path, 'items/images/%s' % item_id) destination = os.path.join(static_path, 'items/images/%s' % cloned_item.id) try: for imgfile in os.listdir(source): shutil.copy(os.path.join(source, imgfile), destination) for image in item.images.filter_by(parent=None).all(): segments = image.path.split('/') segments[3] = str(cloned_item.id) original_img = ItemImage(item=cloned_item, name=image.name, path='/'.join(segments)) for subimage in image.subimages.all(): segments = subimage.path.split('/') segments[3] = str(cloned_item.id) sub_img = ItemImage(item=cloned_item, name=subimage.name, path='/'.join(segments), size=subimage.size, parent=original_img) DBSession.add(sub_img) DBSession.add(original_img) except OSError as e: logger.error("error while cloning images: %s" % str(e)) DBSession.commit() return cloned_item.to_dict() return item.to_dict()
def _create_item_status(self): """ Helper method to create item statuses. """ self.draft_status = ItemStatus('DRAFTS') self.ongoing_status = ItemStatus('ONGOING') self.archived_status = ItemStatus('ARCHIVED') DBSession.add(self.draft_status) DBSession.add(self.ongoing_status) DBSession.add(self.archived_status) DBSession.commit()
def collection_post(self): item_id = int(self.request.matchdict['item_id']) item = DBSession.query(Item).filter_by(id=item_id).one() ext = os.path.splitext( self.request.POST['image'].filename)[1] or '.jpg' filename_uuid = uuid.uuid4() filename = '%s%s' % (filename_uuid, ext) # figure out path to the newly uploaded image static_path = pkgr.resource_filename('tradeorsale', 'static') item_images_path = os.path.join('items/images', str(item_id)) item_images_abspath = os.path.join(static_path, item_images_path) image_path = os.path.join(item_images_abspath, filename) # copy file chunk by chunk with open(image_path, 'wb') as handle: while True: data = self.request.POST['image'].file.read(2 << 16) # 128kb if not data: break handle.write(data) logger.info("storing item image to db: item-id(%i) size(original)" % item_id) item_image = ItemImage(item, filename, os.path.join('/%s' % item_images_path, filename)) # / + items/... # build resized images image_sizes = {} for size, dimension in THUMBNAIL_SIZES.items(): resized_filename = '%s_%s%s' % (filename_uuid, size, ext) resized_image_path = os.path.join(item_images_abspath, resized_filename) # resize image logger.info("resizing image to %s" % str(THUMBNAIL_SIZES[size])) try: img = Image.open(image_path) except IOError as e: logger.error("unable to open image: %s" % str(e)) self.request.errors.add('body', 'image', _(u'Unable to read image')) # if we're resizing to medium size, make height relative to width if size == 'medium': basewidth = THUMBNAIL_SIZES[size][0] width_percentage = (basewidth / float(img.size[0])) height_size = int( (float(img.size[1]) * float(width_percentage))) resized_img = img.resize((basewidth, height_size), Image.ANTIALIAS) else: resized_img = ImageOps.fit(img, THUMBNAIL_SIZES[size], Image.ANTIALIAS) resized_img.save(resized_image_path, quality=90, optimize=True) # save resized image to db logger.info("storing item image to db: item-id(%i) size(%s)" % (item_id, size)) item_subimage = ItemImage( item, resized_filename, os.path.join('/%s' % item_images_path, resized_filename), size) item_image.subimages.append(item_subimage) # save original image to db DBSession.add(item_image) DBSession.commit() # return different images sizes image_sizes = { 'id': item_image.id, 'original': assets_url(self.request, item_image.path) } for size in THUMBNAIL_SIZES.keys(): image_sizes[size] = assets_url(self.request, item_image.get_resized_image(size)) return {'item_id': item_id, 'sizes': image_sizes}