def test_saves_promo_img(self, requests_mock, crush_mock): img_path = os.path.join(settings.ROOT, 'mkt', 'site', 'tests', 'images', 'game_1050.jpg') # Mock the image fetch request. with open(img_path, 'r') as content: requests_mock.return_value = mock.Mock(content=content.read(), headers={'ok': 'ok'}, status_code=200) result = fetch_promo_imgs(self.website.pk, 'http://mocked_url.ly') ok_(result) website = Website.objects.all()[0] eq_(website.promo_img_hash, '215dd2a2') # Check the actual saved image on disk. img_dir = website.get_promo_img_dir() for size in mkt.PROMO_IMG_SIZES: img_path = os.path.join(img_dir, '%s-%s.png' % (str(website.id), size)) with public_storage.open(img_path, 'r') as img: checker = ImageCheck(img) assert checker.is_image() eq_(checker.img.size[0], size)
def test_saves_promo_img(self, requests_mock, crush_mock): img_path = os.path.join(settings.ROOT, 'mkt', 'site', 'tests', 'images', 'game_1050.jpg') # Mock the image fetch request. with open(img_path, 'r') as content: requests_mock.return_value = mock.Mock( content=content.read(), headers={'ok': 'ok'}, status_code=200) result = fetch_promo_imgs(self.website.pk, 'http://mocked_url.ly') ok_(result) website = Website.objects.all()[0] eq_(website.promo_img_hash, '215dd2a2') # Check the actual saved image on disk. img_dir = website.get_promo_img_dir() for size in mkt.PROMO_IMG_SIZES: img_path = os.path.join(img_dir, '%s-%s.png' % (str(website.id), size)) with public_storage.open(img_path, 'r') as img: checker = ImageCheck(img) assert checker.is_image() eq_(checker.img.size[0], size)
def check_icons(self, webapp, file_obj=None): manifest = webapp.get_manifest_json(file_obj) biggest = max([int(size) for size in manifest['icons']]) icon_dir = webapp.get_icon_dir() for size in mkt.CONTENT_ICON_SIZES: if not size <= biggest: continue icon_path = os.path.join(icon_dir, '%s-%s.png' % (str(webapp.id), size)) with public_storage.open(icon_path, 'r') as img: checker = ImageCheck(img) assert checker.is_image() eq_(checker.img.size, (size, size))
def _check_image(im_path, abs_url): valid = True img_format = '' with open(im_path, 'rb') as fp: im = ImageCheck(fp) if not im.is_image(): valid = False log.error('image at %s is not an image' % abs_url) if im.is_animated(): valid = False log.error('image at %s is animated' % abs_url) if valid: img_format = im.img.format return valid, img_format
def check_icons(self, webapp, file_obj=None): manifest = webapp.get_manifest_json(file_obj) biggest = max([int(size) for size in manifest['icons']]) icon_dir = webapp.get_icon_dir() for size in mkt.CONTENT_ICON_SIZES: if not size <= biggest: continue icon_path = os.path.join(icon_dir, '%s-%s.png' % (str(webapp.id), size)) with storage.open(icon_path, 'r') as img: checker = ImageCheck(img) assert checker.is_image() eq_(checker.img.size, (size, size))
def test_animated_images(self): img = ImageCheck(open(get_image_path('animated.png'))) assert img.is_animated() img = ImageCheck(open(get_image_path('non-animated.png'))) assert not img.is_animated() img = ImageCheck(open(get_image_path('animated.gif'))) assert img.is_animated() img = ImageCheck(open(get_image_path('non-animated.gif'))) assert not img.is_animated()
def test_junk(self): img = ImageCheck(open(__file__, 'rb')) assert not img.is_image() img = ImageCheck(open(get_image_path('non-animated.gif'))) assert img.is_image()
def check_upload(file_obj, upload_type, content_type): errors = [] upload_hash = '' is_icon = upload_type == 'icon' is_preview = upload_type == 'preview' is_promo_img = upload_type == 'promo_img' is_video = content_type in mkt.VIDEO_TYPES if not any([is_icon, is_preview, is_promo_img, is_video]): raise ValueError('Unknown upload type.') # By pushing the type onto the instance hash, we can easily see what # to do with the file later. ext = content_type.replace('/', '-') upload_hash = '%s.%s' % (uuid.uuid4().hex, ext) loc = os.path.join(settings.TMP_PATH, upload_type, upload_hash) with private_storage.open(loc, 'wb') as fd: for chunk in file_obj: fd.write(chunk) # A flag to prevent us from attempting to open the image with PIL. do_not_open = False if is_video: if not video_library: errors.append(_('Video support not enabled.')) else: video = video_library(loc) video.get_meta() if not video.is_valid(): errors.extend(video.errors) else: check = ImageCheck(file_obj) if (not check.is_image() or content_type not in mkt.IMG_TYPES): do_not_open = True if is_icon: errors.append(_('Icons must be either PNG or JPG.')) else: errors.append(_('Images must be either PNG or JPG.')) if check.is_animated(): do_not_open = True if is_icon: errors.append(_('Icons cannot be animated.')) else: errors.append(_('Images cannot be animated.')) max_size = (settings.MAX_ICON_UPLOAD_SIZE if is_icon else settings.MAX_VIDEO_UPLOAD_SIZE if is_video else settings.MAX_IMAGE_UPLOAD_SIZE if is_preview else None) if max_size and file_obj.size > max_size: do_not_open = True if is_icon or is_video: errors.append( _('Please use files smaller than %s.') % filesizeformat(max_size)) if ((is_icon or is_preview or is_promo_img) and not is_video and not do_not_open): file_obj.seek(0) try: im = Image.open(file_obj) im.verify() except IOError: if is_icon: errors.append(_('Icon could not be opened.')) elif is_preview: errors.append(_('Preview could not be opened.')) elif is_promo_img: errors.append(_('Promo image could not be opened.')) else: size_x, size_y = im.size if is_icon: # TODO: This should go away when we allow uploads for # individual icon sizes. if size_x < 128 or size_y < 128: errors.append(_('Icons must be at least 128px by 128px.')) if size_x != size_y: errors.append(_('Icons must be square.')) elif is_preview: if (size_x < APP_PREVIEW_MINIMUMS[0] or size_y < APP_PREVIEW_MINIMUMS[1]) and ( size_x < APP_PREVIEW_MINIMUMS[1] or size_y < APP_PREVIEW_MINIMUMS[0]): errors.append( # L10n: {0} and {1} are the height/width of the preview # in px. _('App previews must be at least {0}px by {1}px or ' '{1}px by {0}px.').format(*APP_PREVIEW_MINIMUMS)) elif is_promo_img: if (size_x < PROMO_IMG_MINIMUMS[0] or size_y < PROMO_IMG_MINIMUMS[1]): # Currently, not l10n'ed because for curator eyes only. errors.append( 'Promo images must be at least {0}px by {1}px' .format(*PROMO_IMG_MINIMUMS)) return errors, upload_hash