def setUp(self): self.cloud_name = 'test123' self.public_id = "sample" self.image_format = "jpg" self.full_public_id = "{id}.{format}".format(id=self.public_id, format=self.image_format) self.upload_url = "http://res.cloudinary.com/{cloud_name}/image/upload".format(cloud_name=self.cloud_name) self.common_format = {"url": self.upload_url, "id": self.full_public_id} self.image = CloudinaryImage(self.public_id, format=self.image_format) self.common_transformation = {"effect": "sepia"} self.common_transformation_str = 'e_sepia' self.common_image_options = {"cloud_name": self.cloud_name} self.common_image_options.update(self.common_transformation) self.custom_attributes = {'custom_attr1': 'custom_value1', 'custom_attr2': 'custom_value2'} self.min_width = 100 self.max_width = 399 self.breakpoint_list = [self.min_width, 200, 300, self.max_width] self.common_srcset = {"breakpoints": self.breakpoint_list} self.fill_transformation = {"width": self.max_width, "height": self.max_width, "crop": "fill"} self.fill_transformation_str = "c_fill,h_{h},w_{w}".format(h=self.max_width, w=self.max_width) cloudinary.reset_config() cloudinary.config(cloud_name=self.cloud_name, api_secret="1234", cname=None)
def shared_client_hints(self, **options): """should not use data-src or set responsive class""" tag = CloudinaryImage('sample.jpg').image(**options) self.assertRegexpMatches( tag, '<img.*>', "should not use data-src or set responsive class") self.assertNotRegexpMatches( tag, '<.* class.*>', "should not use data-src or set responsive class") self.assertNotRegexpMatches( tag, '\bdata-src\b', "should not use data-src or set responsive class") self.assertRegexpMatches( tag, 'src=["\']http://res.cloudinary.com/test/image/upload/c_scale,dpr_auto,w_auto/sample.jpg["\']', "should not use data-src or set responsive class") cloudinary.config(responsive=True) tag = CloudinaryImage('sample.jpg').image(**options) self.assertRegexpMatches(tag, '<img.*>') self.assertNotRegexpMatches(tag, '<.* class.*>', "should override responsive") self.assertNotRegexpMatches(tag, '\bdata-src\b', "should override responsive") self.assertRegexpMatches( tag, 'src=["\']http://res.cloudinary.com/test/image/upload/c_scale,dpr_auto,w_auto/sample.jpg["\']', "should override responsive")
def test_srcset_from_string(self): """Should support srcset string value""" raw_srcset_value = "some srcset data as is" attributes = {"srcset": raw_srcset_value} tag = CloudinaryImage(self.full_public_id).image(attributes=attributes, **self.common_image_options) expected_tag = self._get_expected_cl_image_tag(self.full_public_id, self.common_transformation_str, attributes=attributes) self.assertEqual(expected_tag, tag) legacy_tag = CloudinaryImage(self.full_public_id).image(srcset=raw_srcset_value, **self.common_image_options) self.assertEqual(expected_tag, legacy_tag)
def shared_client_hints(self, **options): """should not use data-src or set responsive class""" tag = CloudinaryImage(self.full_public_id).image(**options) six.assertRegex(self, tag, '<img.*>', "should not use data-src or set responsive class") self.assertIsNone(re.match('<.* class.*>', tag), "should not use data-src or set responsive class") self.assertIsNone(re.match('\bdata-src\b', tag), "should not use data-src or set responsive class") expected_re = 'src=["\']{url}/c_scale,dpr_auto,w_auto/{id}["\']'.format(**self.common_format) six.assertRegex(self, tag, expected_re, "should not use data-src or set responsive class") cloudinary.config(responsive=True) tag = CloudinaryImage(self.full_public_id).image(**options) six.assertRegex(self, tag, '<img.*>') self.assertIsNone(re.match('<.* class.*>', tag), "should override responsive") self.assertIsNone(re.match('\bdata-src\b', tag), "should override responsive") six.assertRegex(self, tag, expected_re, "should override responsive")
def test_srcset_with_one_image(self): """Should support 1 image in srcset""" srcset_params = {"min_width": self.min_width, "max_width": self.max_width, "max_images": 1} tag_by_params = CloudinaryImage(self.full_public_id).image(srcset=srcset_params, **self.common_image_options) expected_tag = self._get_expected_cl_image_tag(self.full_public_id, self.common_transformation_str, srcset_breakpoints=[self.max_width]) self.assertEqual(expected_tag, tag_by_params) srcset_breakpoint = {"breakpoints": [self.max_width]} tag_by_breakpoint = CloudinaryImage(self.full_public_id).image(srcset=srcset_breakpoint, **self.common_image_options) self.assertEqual(expected_tag, tag_by_breakpoint)
def test_validate(self): """should validate signature """ self.assertFalse(self.image.validate()) self.assertFalse( CloudinaryImage("hello", format="png", version="1234", signature="1234").validate()) self.assertTrue( CloudinaryImage( "hello", format="png", version="1234", signature="2aa73bf69fb50816e5509e32275b8c417dcb880d").validate( ))
def resolve_thumbnail_tag(self, *args): if self.avatar: src = CloudinaryImage(str(self.avatar)).build_url(width=263, height=225) return src else: return ""
def test_source_tag_responsive_srcset(self): """should generate source tag with responsive srcset""" tag = CloudinaryImage(self.full_public_id).source(srcset=self.common_srcset) expected_tag = self._get_expected_cl_source_tag(self.full_public_id, "", srcset_breakpoints=self.breakpoint_list) self.assertEqual(expected_tag, tag)
def setUp(self): self.cloud_name = 'test123' self.public_id = "sample" self.image_format = "jpg" self.full_public_id = "{id}.{format}".format(id=self.public_id, format=self.image_format) self.upload_url = "http://res.cloudinary.com/{cloud_name}/image/upload".format( cloud_name=self.cloud_name) self.common_format = { "url": self.upload_url, "id": self.full_public_id } self.image = CloudinaryImage(self.public_id, format=self.image_format) self.common_image_options = { "effect": "sepia", "cloud_name": self.cloud_name } self.common_transformation_str = 'e_sepia' self.breakpoint_list = [100, 200, 300, 399] self.common_srcset = {"breakpoints": self.breakpoint_list} self.custom_attributes = { 'custom_attr1': 'custom_value1', 'custom_attr2': 'custom_value2' } cloudinary.reset_config() cloudinary.config(cloud_name=self.cloud_name, api_secret="1234", cname=None)
def test_custom_attributes(self): """ Should consume custom attributes from 'attributes' key""" tag = CloudinaryImage(self.full_public_id).image(attributes=self.custom_attributes, **self.common_image_options) expected_tag = self._get_expected_cl_image_tag(self.full_public_id, self.common_transformation_str, attributes=self.custom_attributes) self.assertEqual(expected_tag, tag)
def test_client_hints_as_false(self): """should use normal responsive behaviour""" cloudinary.config(responsive=True) tag = CloudinaryImage('sample.jpg').image(width="auto", crop="scale", cloud_name="test", client_hints=False) six.assertRegex(self, tag, '<img.*>') six.assertRegex(self, tag, 'class=["\']cld-responsive["\']') six.assertRegex(self, tag, 'data-src=["\']http://res.cloudinary.com/test/image/upload/c_scale,w_auto/sample.jpg["\']')
def test_srcset_from_float_breakpoints(self): """Should create srcset attribute with provided breakpoints as float values""" float_breakpoint_list = [bp + 0.1 for bp in self.breakpoint_list] self.common_srcset = {"breakpoints": float_breakpoint_list} tag = CloudinaryImage(self.full_public_id).image(srcset=self.common_srcset, **self.common_image_options) expected_tag = self._get_expected_cl_image_tag(self.full_public_id, self.common_transformation_str, srcset_breakpoints=float_breakpoint_list) self.assertEqual(expected_tag, tag)
def test_width_auto_breakpoints(self): """supports auto width""" tag = CloudinaryImage('sample.jpg')\ .image(crop="scale", dpr="auto", cloud_name="test", width="auto:breakpoints", client_hints=True) six.assertRegex( self, tag, 'src=["\']http://res.cloudinary.com/test/image/upload/c_scale,dpr_auto,w_auto:breakpoints/sample.jpg["\']' )
def get_image(self): """ Property method to fetch profile image """ image_url = CloudinaryImage(str(self.image)).build_url( width=80, height=120, crop="fill" ) return image_url
def to_python(self, value): if isinstance(value, CloudinaryImage): return value if not value: return value m = re.search(r'(?:v(\d+)/)?(.*)\.(.*)', value) return CloudinaryImage(m.group(2), version=m.group(1), format=m.group(3))
def to_python(self, value): "Upload and convert to CloudinaryImage" value = super(CloudinaryFileField, self).to_python(value) if not value: raise forms.ValidationError("No image selected!") result = cloudinary.uploader.upload(value) return CloudinaryImage(result["public_id"], version=str(result["version"]), format=result["format"])
def build_url(query): full = [] for i, im in enumerate(query): query[i]["url"] = CloudinaryImage(im["url"]).build_url( crop="scale", dpr="auto", width="auto", responsive=True, responsive_placeholder="blank", secure=True, ) full.append( CloudinaryImage(im["url"]).build_url( crop="scale", secure=True, width=1080, )) return zip(query, full)
def test_custom_attributes_override_existing(self): """ Attributes from 'attributes' dict should override existing attributes""" updated_attributes = {"alt": "updated alt"} tag = CloudinaryImage(self.full_public_id).image(alt="original alt", attributes=updated_attributes, **self.common_image_options) expected_tag = self._get_expected_cl_image_tag(self.full_public_id, self.common_transformation_str, attributes=updated_attributes) self.assertEqual(expected_tag, tag)
def test_custom_attributes_legacy(self): """ Should consume custom attributes as is from options""" custom_options = copy.deepcopy(self.common_image_options) custom_options.update(self.custom_attributes) tag = CloudinaryImage(self.full_public_id).image(**custom_options) expected_tag = self._get_expected_cl_image_tag(self.full_public_id, self.common_transformation_str, attributes=self.custom_attributes) self.assertEqual(expected_tag, tag)
def test_srcset_width_height_removed(self): """Should remove width and height attributes in case srcset is specified, but passed to transformation""" tag = CloudinaryImage(self.full_public_id).image(width=500, height=500, srcset=self.common_srcset, **self.common_image_options) expected_tag = self._get_expected_cl_image_tag(self.full_public_id, self.common_transformation_str + ",h_500,w_500", srcset_breakpoints=self.breakpoint_list) self.assertEqual(expected_tag, tag)
def test_client_hints_as_false(self): """should use normal responsive behaviour""" cloudinary.config(responsive=True) tag = CloudinaryImage(self.full_public_id).image(width="auto", crop="scale", cloud_name=self.cloud_name, client_hints=False) six.assertRegex(self, tag, '<img.*>') six.assertRegex(self, tag, 'class=["\']cld-responsive["\']') exp = 'data-src=["\']{url}/c_scale,w_auto/{id}["\']'.format(**self.common_format) six.assertRegex(self, tag, exp)
def test_source_tag_media_query(self): """should generate source tag with media query""" media = {"min_width": self.min_width, "max_width": self.max_width} tag = CloudinaryImage(self.full_public_id).source(media=media) expected_media = "(min-width: {min}px) and (max-width: {max}px)".format(min=self.min_width, max=self.max_width) expected_tag = self._get_expected_cl_source_tag(self.full_public_id, "", attributes={"media": expected_media}) self.assertEqual(expected_tag, tag)
def cloudinary_url(context, source, options_dict={}, **options): options = dict(options_dict, **options) try: if context['request'].is_secure() and 'secure' not in options: options['secure'] = True except KeyError: pass if not isinstance(source, CloudinaryImage): source = CloudinaryImage(source) return source.build_url(**options)
def cloudinary_tag(context, image, options_dict={}, **options): options = dict(options_dict, **options) try: if context['request'].is_secure() and 'secure' not in options: options['secure'] = True except KeyError: pass if not isinstance(image, CloudinaryImage): image = CloudinaryImage(image) return image.image(**options)
def test_srcset_from_min_width_max_width_max_images(self): """Should support srcset attribute defined by min_width, max_width, and max_images""" srcset_params = {"min_width": self.min_width, "max_width": self.max_width, "max_images": len(self.breakpoint_list)} tag = CloudinaryImage(self.full_public_id).image(srcset=srcset_params, **self.common_image_options) expected_tag = self._get_expected_cl_image_tag(self.full_public_id, self.common_transformation_str, srcset_breakpoints=self.breakpoint_list) self.assertEqual(expected_tag, tag)
def test_srcset_with_sizes_attribute(self): """Should populate sizes attribute""" srcset_params = copy.deepcopy(self.common_srcset) srcset_params["sizes"] = True tag = CloudinaryImage(self.full_public_id).image(srcset=srcset_params, **self.common_image_options) expected_sizes_attr = ", ".join("(max-width: {w}px) {w}px".format(w=bp) for bp in self.breakpoint_list) attributes = {"sizes": expected_sizes_attr} expected_tag = self._get_expected_cl_image_tag(self.full_public_id, self.common_transformation_str, srcset_breakpoints=self.breakpoint_list, attributes=attributes) self.assertEqual(expected_tag, tag)
def get_download_url(cls, public_id: str, version: int, width: int = None, height: int = None): transformation = {} if width and height: transformation['width'] = width transformation['height'] = height transformation['crop'] = "fill" current_ts = datetime_to_utc_unix(now()) if not version: version = current_ts if not transformation: return CloudinaryImage(public_id=public_id, version=version).build_url() return CloudinaryImage( public_id=public_id, version=version).build_url(transformation=transformation)
def test_width_auto_breakpoints(self): """supports auto width""" tag = CloudinaryImage(self.full_public_id).image( crop="scale", dpr="auto", cloud_name=self.cloud_name, width="auto:breakpoints", client_hints=True) expected_re = 'src=["\']{url}/c_scale,dpr_auto,w_auto:breakpoints/{id}["\']'.format( **self.common_format) six.assertRegex(self, tag, expected_re)
def test_srcset_invalid_values(self): """Should raise ValueError on invalid values""" invalid_srcset_params = [ { 'sizes': True }, # srcset data not provided { 'max_width': 300, 'max_images': 3 }, # no min_width { 'min_width': '1', 'max_width': 300, 'max_images': 3 }, # invalid min_width { 'min_width': 100, 'max_images': 3 }, # no max_width { 'min_width': 100, 'max_width': '3', 'max_images': 3 }, # invalid max_width { 'min_width': 200, 'max_width': 100, 'max_images': 3 }, # min_width > max_width { 'min_width': 100, 'max_width': 300 }, # no max_images { 'min_width': 100, 'max_width': 300, 'max_images': 0 }, # invalid max_images { 'min_width': 100, 'max_width': 300, 'max_images': -17 }, # invalid max_images { 'min_width': 100, 'max_width': 300, 'max_images': '3' }, # invalid max_images ] for invalid_srcset in invalid_srcset_params: with self.assertRaises(ValueError): CloudinaryImage(self.full_public_id).image( srcset=invalid_srcset, **self.common_image_options)
def to_python(self, value): if isinstance(value, CloudinaryImage): return value elif isinstance(value, UploadedFile): return value elif not value: return value else: m = re.search( '(v(?P<version>\d+)/)?(?P<public_id>.*?)(\.(?P<format>[^.]+))?$', value) return CloudinaryImage(type=self.type, **m.groupdict())