
    gx                         d dl mZ d dlZd dlZd dlZd dlZd dlZd dlmZ d dl	m
Z
 d dlZd dlmZmZ  ej                  d      Z ej"                         Z ej&                  d      Zej+                  e       ej-                  e       d dlmZ d d	lmZ d d
lmZ d dlmZ d dlm Z m!Z! d dl"m#Z#m"Z" d ejH                         dZ%dZ&dZ'dZ(e(Z)dZ*dZ+dZ,dZ-dj]                   e"       dj_                   e#             f      Z0dj_                  e-e0      Z1	 da2	 d Z3d Z4 eejj                         G d de6             Z7 G d d e7      Z8 e8       a9d! Z:d" Z; e       Z<d d#l=m>Z> d d$l?m@Z@ e G d% d&e6             ZA G d' d(eA      ZB G d) d*eA      ZCy)+    )absolute_importN)deepcopy)ceil)python_2_unicode_compatibleadd_metaclass
Cloudinaryz4%(asctime)s - %(name)s - %(levelname)s - %(message)s)utils)GeneralError)responsive_breakpoints_cache)
HttpClient)urlparseparse_qs)python_versionplatformCERT_REQUIRED)	cert_reqsca_certszd3jpl91pxevbkh.cloudfront.netzcloudinary-a.akamaihd.netzres.cloudinary.comzNdata:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
cloudinaryv1_1z1.41.0z; z	Python {}zCloudinaryPython/{} ({}) c                  @    t         dk(  rt        S t         dz   t        z   S )z
    Provides the `USER_AGENT` string that is passed to the Cloudinary servers.
    Prepends  `USER_PLATFORM` if it is defined.

    :returns: the user agent
    :rtype: str
    r    )USER_PLATFORM
USER_AGENT     (/opt/Tautulli/lib/cloudinary/__init__.pyget_user_agentr   <   s"     s"Z//r   c                      	 ddl m}  	 ddlm} d|j                  v rddlm} dj                   |             adt        |      v r|j                  S y # | $ r Y y w xY w# t        $ r Y y w xY w)	Nr   )ImproperlyConfigured)settingsr   )get_versionzDjango/{django_version})django_version
CLOUDINARY)django.core.exceptionsr    django.confr!   INSTALLED_APPSdjangor"   formatr   dirr$   ImportError)r    _django_settings_get_django_versions      r   import_django_settingsr.   K   s    ?	@
 />>>E 9 @ @PcPe @ fs#344'222# 		  s/   A A	A AA AA 	A+*A+c                       e Zd Zd Zd Zed        Zd Zd Zed        Z	e
j                  d        Zd Zd	 Ze
j                  d
        Zd Zy)
BaseConfigc                 `    t               }|r | j                  di | | j                          y Nr   )r.   update_load_config_from_env)selfdjango_settingss     r   __init__zBaseConfig.__init__h   s*    02DKK*/*""$r   c                 8    | j                   j                  |      S N)__dict__get)r5   is     r   __getattr__zBaseConfig.__getattr__o   s    }}  ##r   c                 .    t        j                  d|       S )Nz
\w+\[\w+\])rematch)keys    r   _is_nested_keyzBaseConfig._is_nested_keyr   s    xxs++r   c                    t        j                  d|      }|D cg c]  }|s|	 }}| j                  }|j                         }|D ]  }||v r||   }nt	               }|||<   |} t        |t              r|d   }|||<   y c c}w )Nz[\[\]]+r   )r?   splitr:   popdict
isinstancelist)	r5   rA   valuechainkouterlast_key	inner_keyinners	            r   _put_nested_keyzBaseConfig._put_nested_keyv   s    S)!'qQ''99; 	IE!i(#(i E	 eT"!HEh (s
   BBc                 P    |j                   j                         | j                  k(  S )z
        Helper function. Validates url scheme

        :param url: A named tuple containing URL components

        :return: bool True on success or False on failure
        )schemelower_uri_scheme)r5   urls     r   _is_url_scheme_validzBaseConfig._is_url_scheme_valid   s"     zz!T%5%555r   c                     t        |       S r9   )r   )cloudinary_urls    r   _parse_cloudinary_urlz BaseConfig._parse_cloudinary_url   s    ''r   c                     t               )z.Extract additional config from the parsed URL.NotImplementedError)r5   
parsed_urls     r   _config_from_parsed_urlz"BaseConfig._config_from_parsed_url        "##r   c                    | j                  |      } | j                  di | t        |j                        j	                         D ];  \  }}| j                  |      r| j                  ||       *|d   | j                  |<   = y Nr   r   )r^   r3   r   queryitemsrB   rP   r:   )r5   r]   config_from_parsed_urlrK   vs        r   _setup_from_parsed_urlz!BaseConfig._setup_from_parsed_url   s|    !%!=!=j!I-,-Z--.446 	(DAq""1%$$Q*#$Q4a 		(r   c                 F    | j                  |      }| j                  |      S r9   )rY   rf   )r5   rU   r]   s      r   _load_from_urlzBaseConfig._load_from_url   s#    //4
**:66r   c                     t               )z.Load config from environment variables or URL.r[   r5   s    r   r4   z BaseConfig._load_config_from_env   r_   r   c                 R    |j                         D ]  \  }}|| j                  |<    y r9   )rc   r:   )r5   keywordsrK   re   s       r   r3   zBaseConfig.update   s*    NN$ 	!DAq DMM!	!r   N)__name__
__module____qualname__r7   r=   staticmethodrB   rP   rV   rY   abcabstractmethodr^   rf   rh   r4   r3   r   r   r   r0   r0   f   s    %$ , ,  6 ( ( 	$ $(7
 	$ $!r   r0   c                   *     e Zd Z fdZd Zd Z xZS )Configc                     t         | _        t        t        |           | j
                  st        j                  | _        y y r9   )
URI_SCHEMErT   superrt   r7   signature_algorithmr	   SIGNATURE_SHA1)r5   	__class__s    r   r7   zConfig.__init__   s4    %fd$&''',';';D$ (r   c                     | j                  |      st        d      |j                  dk7  }|j                  |j                  |j
                  |d}|r |j                  d|j                  dd  i       |S )NzFInvalid CLOUDINARY_URL scheme. Expecting to start with 'cloudinary://'r   )
cloud_nameapi_key
api_secretprivate_cdnsecure_distribution   )rV   
ValueErrorpathhostnameusernamepasswordr3   )r5   r]   is_private_cdnresults       r   r^   zConfig._config_from_parsed_url   sv    ((4eff#B.$--!**$--)	
 MM0*//!"2EFGr   c                    t         j                  j                  d      rt         j                  j                         D cg c]  }|j	                  d      r|dk7  r| }}|D ]N  }|t        d      d  j                         }t         j                  |   }|dv r|dk(  } | j                  di ||i P y t         j                  j                  d      r/| j                  t         j                  j                  d             y y c c}w )NCLOUDINARY_CLOUD_NAMECLOUDINARY_CLOUDINARY_URL)truefalser   r   )	osenvironr;   keys
startswithlenrS   r3   rh   )r5   rA   config_keysfull_keyconf_keyconf_vals         r   r4   zConfig._load_config_from_env   s    ::>>12*,**//*; Y3!nn];GW@W  YK Y ( 4#C$6$78>>@::h/00'61H3x234 ZZ^^,-

/? @A .Ys    D)rm   rn   ro   r7   r^   r4   __classcell__rz   s   @r   rt   rt      s    < Br   rt   c                  8    t        j                  di |  t         S r2   )_configr3   )rl   s    r   configr      s    NNXNr   c                      t               ay r9   )rt   r   r   r   r   reset_configr      s	    hGr   )Search)SearchFoldersc                   T   e Zd ZdZddddidddddidddd	id
ddd	id
gZ	 	 	 d)dZd Zd Zd Zd Z	d Z
d Zed        Zd Zd Zed        Zed        Zed        Zd Zd*dZd Zd*dZed        Zd Zd Zd  Zed*d!       Zed"        Zd# Zd$ Zd% Z ed&        Z!d' Z"d( Z#y)+CloudinaryResourcez+
    Recommended sources for video tag
    mp4hev1video_codech265)typecodecstransformationswebmvp9auto)r   r   Nc
                 |   || _         |xs i }|xs |j                  d      | _        |xs |j                  d      | _        |xs |j                  d      | _        |xs |j                  d      | _        |xs |j                  d      xs d| _        |xs |j                  d      xs |	| _        |xs i | _        y )N	public_idr)   version	signaturer   uploadresource_type)	metadatar;   r   r)   r   r   r   r   url_options)
r5   r   r)   r   r   r   r   r   r   default_resource_types
             r   r7   zCloudinaryResource.__init__  s     !>r"?hll;&?6X 69(,,y"9"?hll;&?<HLL0<H	*dhll?.KdOd&,"r   c                     | j                   S r9   )r   rj   s    r   __str__zCloudinaryResource.__str__  s    ~~r   c                 H    | j                   t        | j                         S dS )Nr   )r   r   rj   s    r   __len__zCloudinaryResource.__len__  s    &*nn&@s4>>"GaGr   c                 <    | j                   | j                         k(  S r9   )r   get_expected_signaturerj   s    r   validatezCloudinaryResource.validate  s    ~~!<!<!>>>r   c                 H   d | j                   | j                  | j                  fv ry d}|| j                  z   dz   | j                  z   dz   }| j                  r|dz   t	        | j                        z   dz   }|| j                   z   }| j
                  r|dz   | j
                  z   }|S )Nr   /re   .)r   r   r   r   strr)   )r5   preps     r   get_prep_valuez!CloudinaryResource.get_prep_value  s    DNNII&&( ( d(((3.:S@<<#:DLL 11C7Ddnn$;;#:+Dr   c                 J    | j                         dz   | j                         z   S )N#)r   r   rj   s    r   get_presignedz CloudinaryResource.get_presigned+  s$    ""$s*T-H-H-JJJr   c                     t        j                  | j                  | j                  dt	               j
                  t	               j                        S )N)r   r   )r	   api_sign_requestr   r   r   r~   rx   rj   s    r   r   z)CloudinaryResource.get_expected_signature.  s=    %%DNNt||&\^d^f^q^q&,h&B&BD 	Dr   c                 :     | j                   di | j                  S r2   )	build_urlr   rj   s    r   rU   zCloudinaryResource.url2  s    t~~1 0 011r   c                    t        | j                  | j                  | j                  | j                  xs d      }|j                  |       |j                  d      xs | j                  }t        j                  |fi |S )Nimage)r)   r   r   r   r   )
rF   r)   r   r   r   r3   r;   r   r	   rX   )r5   optionscombined_optionsr   s       r   __build_urlzCloudinaryResource.__build_url6  sl    t{{DLLtyy.2.@.@.KGM($((5G	##IB1ABBr   c                 ,     | j                   di |d   S ra   )_CloudinaryResource__build_urlr5   r   s     r   r   zCloudinaryResource.build_url=  s    t*'*1--r   c                 .    | j                  dd      | d<   y )Nr)   jpg)r;   )r   s    r   default_poster_optionsz)CloudinaryResource.default_poster_options@  s    #KK%8r   c                  
    g dS )N)r   r   ogvr   r   r   r   default_source_typesz'CloudinaryResource.default_source_typesD  s    %%r   c                      t         fddD              st        j                  d       y d    d   kD  rt        j                  d       y d   d	k  rt        j                  d
       yy)a  
        Helper function. Validates srcset_data parameters

        :param srcset_data: A dictionary containing the following keys:
                breakpoints A list of breakpoints.
                min_width   Minimal width of the srcset images
                max_width   Maximal width of the srcset images.
                max_images  Number of srcset images to generate.

        :return: bool True on success or False on failure
        c              3   d   K   | ]'  }|v xr t        |   t        j                         ) y wr9   )rG   numbersNumber).0rK   srcset_datas     r   	<genexpr>z;CloudinaryResource._validate_srcset_data.<locals>.<genexpr>U  s4      lWX1#R
;q>7>>(RR ls   -0)	min_width	max_width
max_imageszlEither valid (min_width, max_width, max_images)or breakpoints must be provided to the image srcset attributeFr   r   z%min_width must be less than max_widthr   r   z%max_images must be a positive integerT)allloggerwarning)r   s   `r   _validate_srcset_dataz(CloudinaryResource._validate_srcset_dataH  sy      l ]k l lNN [ \{#k+&>>NNBC|$)NNBCr   c                 T   |j                  dt                     }|r|S | j                  |      sy|d   |d   |d   }}}|dk(  r|}t        t	        t        ||z
        |dkD  r|dz
  ndz              }|}||k  r|j                  |       ||z  }||k  r|j                  |       |S )a  
        Helper function. Calculates static responsive breakpoints using provided parameters.

        Either the breakpoints or min_width, max_width, max_images must be provided.

        :param srcset_data: A dictionary containing the following keys:
                                breakpoints A list of breakpoints.
                                min_width   Minimal width of the srcset images
                                max_width   Maximal width of the srcset images.
                                max_images  Number of srcset images to generate.

        :return: A list of breakpoints

        :raises ValueError: In case of invalid or missing parameters
        breakpointsNr   r   r   r   )r;   rH   r   intr   floatappend)r5   r   r   r   r   r   	step_sizecurr_breakpoints           r   _generate_breakpointsz(CloudinaryResource._generate_breakpointse  s      "oomTV<))+6+6{+C[Q\E]_jkw_xj9	?!IU9y#89z\]~Z!^cdefg	#	)/y(O 	) 	9%r   c                    |
t               }|j                  dd      }|j                  dd      }|j                  dd      }|j                  dd	      }|j                  d
      }t        t        t	        |      dz              }dj                  ||||      }	t        j                  | j                  |	||      }
t        j                  |
      j                  dd      S )a  
        Helper function. Retrieves responsive breakpoints list from cloudinary server

        When passing special string to transformation `width` parameter of form `auto:breakpoints{parameters}:json`,
        the response contains JSON with data of the responsive breakpoints

        :param srcset_data: A dictionary containing the following keys:
                                min_width   Minimal width of the srcset images
                                max_width   Maximal width of the srcset images
                                bytes_step  Minimal bytes step between images
                                max_images  Number of srcset images to generate
        :param options: Additional options

        :return: Resulting breakpoints
        Nr   2   r   i  
bytes_stepi N  r      transformationi   zHauto:breakpoints_{min_width}_{max_width}_{kbytes_step}_{max_images}:json)r   r   kbytes_stepr   r   )rF   r;   r   r   r   r)   r	   cloudinary_scaled_urlr   _http_clientget_json)r5   r   r   r   r   r   r   r   r   breakpoints_width_parambreakpoints_urls              r   _fetch_breakpointsz%CloudinaryResource._fetch_breakpoints  s      &KOOK4	OOK6	 __\59
 __\26
$)9:$uZ04789"l"s"s9+Zd #t #f55dnnF]_movw$$_599-NNr   c                    |j                  d      }|r|S |j                  d      rmt        j                  j                   | j                  fi |}|sA	  | j                  |fi |}|r+t        j                  j                  | j                  |fi | |s| j                  |      }|S # t
        $ r9}t        j                  dj                  |j                               Y d}~d}~ww xY w)a:  
        Helper function. Gets from cache or calculates srcset breakpoints using provided parameters

        :param srcset_data: A dictionary containing the following keys:
                                breakpoints A list of breakpoints.
                                min_width   Minimal width of the srcset images
                                max_width   Maximal width of the srcset images
                                max_images  Number of srcset images to generate
        :param options: Additional options

        :return: Resulting breakpoints
        r   	use_cachez.Failed getting responsive breakpoints: {error})errorN)r;   r   instancer   r   r
   r   r   r)   messagesetr   )r5   r   r   r   es        r   _get_or_generate_breakpointsz/CloudinaryResource._get_or_generate_breakpoints  s     "oom4??;'6??CCDNN^V]^Km"9$"9"9+"Q"QK 099==dnnke]de44[AK $ mNN#S#Z#Zabajaj#Z#kllms   B) )	C+2/C&&C+c                     |sy|
t               }dj                  |D cg c]4  }dj                  t        j                  | j
                  |||      |      6 c}      S c c}w )aj  
        Helper function. Generates srcset attribute value of the HTML img tag.

        :param breakpoints: A list of breakpoints.
        :param transformation: Custom transformation
        :param options:     Additional options

        :return:  Resulting srcset attribute value

        :raises ValueError: In case of invalid or missing parameters
        N, z{0} {1}w)rF   joinr)   r	   r   r   )r5   r   r   r   ws        r   _generate_srcset_attributez-CloudinaryResource._generate_srcset_attribute  sp     !!VNyyEPR@A %++E,G,GNNA~w-89:< R S 	S Rs   9Ac                 8    | sydj                  d | D              S )z
        Helper function. Generates sizes attribute value of the HTML img tag.

        :param breakpoints: A list of breakpoints.

        :return: Resulting 'sizes' attribute value
        Nr  c              3   @   K   | ]  }d j                  |        yw)z(max-width: {bp}px) {bp}px)bpN)r)   )r   r	  s     r   r   z?CloudinaryResource._generate_sizes_attribute.<locals>.<genexpr>  s     Z5<<<CZs   )r  )r   s    r   _generate_sizes_attributez,CloudinaryResource._generate_sizes_attribute  s     yyZkZZZr   c                 4   t               }|s|S d}d|vr? | j                  |fi |}|j                  d      } | j                  ||fi |}|r||d<   d|vr@|j                  d      du r-|s | j                  |fi |}| j	                  |      }|r||d<   |S )a  
        Helper function. Generates srcset and sizes attributes of the image tag

        Create both srcset and sizes here to avoid fetching breakpoints twice

        :param attributes: Existing attributes
        :param srcset_data: A dictionary containing the following keys:
                                breakpoints     A list of breakpoints.
                                min_width       Minimal width of the srcset images
                                max_width       Maximal width of the srcset images.
                                max_images      Number of srcset images to generate.
        :param options:     Additional options

        :return: The responsive attributes
        Nsrcsetr   sizesT)rF   r  r;   r  r
  )	r5   
attributesr   r   responsive_attributesr   r   srcset_attr
sizes_attrs	            r   %_generate_image_responsive_attributesz8CloudinaryResource._generate_image_responsive_attributes  s      !%((:%;$;;KS7SK(__-=>N9$99+~aY`aK2=%h/*$)AT)I?d??WwW77DJ1;%g.$$r   c                    |j                  d| j                        dk(  r| j                  |       |j                  dt	                     }|j                  dt	                     }t	               }t        |t              rBt               j                  xs
 t	               }|j                         }|j                  |       n	d|vr||d<    | j                  di |\  }}|j                  dt               j                        }|j                  dd      }|j                  dd      }	|s|	rP|sN||d	<   |rd
nd}
d|v r|
d|d   z   z  }
|
|d<   |j                  dt               j                        }|dk(  rt        } | j                  ||fi |}|rdD ]  }|j                  |d        |j                  |       |j                  |       |r||d<   dj                  t!        j"                  |            S )zx
        Generates HTML img tag

        :param options: Additional options

        :return: Resulting img tag
        r   videor  r  client_hints
responsiveFhidpizdata-srczcld-responsivez	cld-hidpiclassr   responsive_placeholderblank>   widthheightNsrcz
<img {0}/>r   )r;   r   r   rE   rF   rG   r   r  copyr3   r   r  r  CL_BLANKr  r)   r	   
html_attrs)r5   r   custom_attributessrcset_optionr   r  attrsr  r  r  classesresponsive_attrsrA   s                r   r   zCloudinaryResource.image  s    ;;(:(:;wF''0#KKdf=Hdf5fmT* (//3TVK%**,K}-00.;!(+%T%%00
Uyy1F1FGYY|U3
		'5)% #E**4&+G%3w//$E'N))4fh6U6UVCg~E4EEFWYdphop* %		#t$% 	%&&'E%L##E$4$4U$;<<r   c                 H    | j                  |        | j                  di |S r2   )r   r   r   s     r   video_thumbnailz"CloudinaryResource.video_thumbnailX  s$    ##G,t~~(((r   c                     | dk(  rdn| } | syt        |t        t        f      rdj                  |      n|}|rdj	                  |      nd}dj	                  | |      S )a  
        Helper function for video(), generates video MIME type string from video_type and codecs.
        Example: video/mp4; codecs=mp4a.40.2

        :param video_type: mp4, webm, ogg etc.
        :param codecs: List or string of codecs. E.g.: "avc1.42E01E" or "avc1.42E01E, mp4a.40.2" or
                       ["avc1.42E01E", "mp4a.40.2"]

        :return: Resulting mime type
        r   oggr   r  z; codecs={codecs_str})
codecs_strz
video/{}{})rG   rH   tupler  r)   )
video_typer   r*  codecs_attrs       r   _video_mime_typez#CloudinaryResource._video_mime_type\  sb     )E1Uz
*4VdE]*KTYYv&QW
OY-44
4K_a"":{;;r   c                     | j                         }d|v r|j                  d      |d<   d|v r|j                  d      |d<   d|v r|d   s|j                  dd       |S )z
        Helper function for video tag, collects remaining options and returns them as attributes

        :param video_options: Remaining options

        :return: Resulting attributes
        
html_widthr  html_heightr  posterN)r  rE   )video_optionsr  s     r   _collect_video_tag_attributesz0CloudinaryResource._collect_video_tag_attributess  sk     #'')
:%",..">JwJ&#->>-#@Jx z!*X*>NN8T*r   c                     d|vr | j                   dd|i|S |d   }t        |t              s|S d|vr | j                   dd|i|S t        j                  |d   fi |d   S )z
        Helper function for video tag, generates video poster URL

        :param source: The public ID of the resource
        :param video_options: Additional options

        :return: Resulting video poster URL
        r2  r   r   r   )r'  rG   rF   r	   rX   )r5   sourcer3  poster_optionss       r   _generate_video_poster_attrz.CloudinaryResource._generate_video_poster_attr  s     =('4''J&JMJJ&x0.$/!!n,'4''K&KNKK##N;$?R>RSTUUr   c                    g }|j                  dg       }|j                  dg       }|j                  di       }|rt        |t              r|D ]  }|j                         }|j	                  |j                  di              |j                  dd      }	t        j                  |fd|	i|d   }
|j                  d	g       }|j                  d
j                  t        j                  |
| j                  |	|      d                    |S |s| j                         }t        |t        t        f      s|S |D ]  }	|j                         }|j	                  |j                  |	i              t        j                  |fd|	i|d   }
|j                  d
j                  t        j                  |
| j                  |	      d                    |S )a  
        Helper function for video tag, populates source tags from provided options.

        source_types and sources are mutually exclusive, only one of them can be used.
        If both are not provided, source types are used (for backwards compatibility)

        :param source: The public ID of the video
        :param options: Additional options

        :return: Resulting source tags (may be empty)
        sourcessource_typessource_transformationr   r   r   r)   r   r   z<source {attributes}>)r  r   )r  )rE   rG   rH   r  r3   r;   r	   rX   r   r)   r   r.  r   r+  )r5   r6  r   source_tagsvideo_sourcesr;  r<  source_datar   source_typer  r   s               r   _populate_video_source_tagsz.CloudinaryResource._populate_video_source_tags  s      Ir2{{>26 ',CR HZt<, t!(%%koo6G&LM)oofb9**6X+XXYZ[$26""#:#A#A$//TEZEZ[fhnEo0pq $B $s tt  446L,u6' 	hK$\\^N!!"7";";K"LM&&vTkT^TUVWC6== ++CAVAVWbAc,de  >  g h		h r   c                 x   |j                  d| j                        }|j                  dt               j                        }|sDt	        j
                  dj                  dj                  | j                                     d|      }n|}|j                  dt                     }|j                  dd      }|j                  dd      }|j                         }d	|vr| j                  ||      |d	<   d
|vr| j                  xs d|d
<   | j                  ||      }	|	s|dz   t        j                   |      d   z   }t        j"                  |fi |\  }
}|	s|
|d<   | j%                  |      }|j'                  |       dj                  d |	D              }dj                  t        j(                  |      ||      }|S )a]  
        Creates an HTML video tag for the provided +source+

        Examples:
           CloudinaryResource("mymovie.mp4").video()
           CloudinaryResource("mymovie.mp4").video(source_types = 'webm')
           CloudinaryResource("mymovie.ogv").video(poster = "myspecialplaceholder.jpg")
           CloudinaryResource("mymovie.webm").video(source_types = ['webm', 'mp4'], poster = {'effect': 'sepia'})

        :param options:
         * <tt>source_types</tt>            - Specify which source type the tag should include.
                                              defaults to webm, mp4 and ogv.
         * <tt>sources</tt>                 - Similar to source_types, but may contain codecs list.
                                              source_types and sources are mutually exclusive, only one of
                                              them can be used. If both are not provided, default source types
                                              are used.
         * <tt>source_transformation</tt>   - specific transformations to use
                                              for a specific source type.
         * <tt>poster</tt>                  - override default thumbnail:
           * url: provide an ad hoc url
           * options: with specific poster transformations and/or Cloudinary +:public_id+

        :return: Video tag
        r   use_fetch_formatz\.({0})$|r   r  fallback_contentr;  r2  r   r  r   r   r  c              3   2   K   | ]  }t        |        y wr9   )r   )r   xs     r   r   z+CloudinaryResource.video.<locals>.<genexpr>
  s     :c!f:s   z/<video {attributes}>{sources}{fallback}</video>)r  r:  fallback)r;   r   r   rC  r?   subr)   r  r   rE   rF   r  r8  r   rA  r	   build_arrayrX   r4  r3   r   )r5   r   r   rC  r6  r!  rH  r;  r7  r=  	video_urlr3  r  sources_strhtmls                  r   r  zCloudinaryResource.video  s   2 KKT^^<	";;'968;T;TUVVK..sxx8Q8Q8S/TUWY[deFF#KKdf=;;126 {{>26 ,, $ @ @ XGH')'+'9'9'DWGO$ 66vwGc\E$5$5l$CA$FFF#(#7#7#J'#J 	='0e$77F
+,gg:k::@GG''
3[S[ H ] r   c                      g }d| v r#|j                  dj                  | d                d| v r#|j                  dj                  | d                dj                  |      S )Nr   z(min-width: {}px)r   z(max-width: {}px)z and )r   r)   r  )media_optionsmedia_query_conditionss     r   __generate_media_attrz(CloudinaryResource.__generate_media_attr  sh    !#-'"))*=*D*D]S^E_*`a-'"))*=*D*D]S^E_*`a||233r   c                    |j                  d      xs i }t               j                  xs
 t               }|j	                         }|j                  |j                  dt                             | j                  ||fi |}|j                  |       d|vr | j                  di |\  |d<   }d|vr) | j                  di |j                  di       }|r||d<   dj                  t        j                  |            S )Nr  r  mediaz<source {0}>r   )r;   r   r  rF   r  r3   rE   r  r   (_CloudinaryResource__generate_media_attrr)   r	   r   )r5   r   r#  r   r%  _
media_attrs          r   r6  zCloudinaryResource.source  s    L)/Rhoo/!&&(7;;x89E4EEe[d\cd%& 5 !1!1!1!<G!<E(OQ%333Qw{{7B7OQJ!+g%%e&6&6u&=>>r   c                    g }|j                  d      xs
 t               }|D ]b  t        |      }dv rt        j                  |d         }t        fddD              |d<   |j                   | j                  di |       d |j                   | j                  di |       dj                  dj                  |            S )	Nr:  r   c              3   6   K   | ]  }|v s||   f  y wr9   r   )r   rK   r6  s     r   r   z-CloudinaryResource.picture.<locals>.<genexpr>9  s"     (kA_`dj_j!VAY(ks   	)r   r   rS  z<picture>{}</picture>r   r   )rE   rH   r   r	   chain_transformationsrF   r   r6  r   r)   r  )r5   r   sub_tagsr:  curr_optionsr6  s        @r   picturezCloudinaryResource.picture0  s    ++i(2DF 	9F#G,L6)$::<P`Iab$((kA[(k$kL!OOKDKK7,78	9 	


-W-.'..rwwx/@AAr   )	NNNNNNNNNr9   )$rm   rn   ro   __doc__default_video_sourcesr7   r   r   r   r   r   r   propertyrU   r   r   rp   r   r   r   r   r   r  r  r
  r  r   r'  r.  r4  r8  rA  r  rT  r6  r\  r   r   r   r   r      s   
  -v6	

  -u5

  -v6
  -v6
$ =A[_'+-H?KD 2 2C. 9 9 & &  8(TOB"HS* [ [%%N8=t) < <,  (V,.`@D 4 4?,Br   r   c                         e Zd Zd fd	Z xZS )CloudinaryImagec                 2    t        t        | 
  d|dd| y )Nr   r   r   r   )rw   ra  r7   r5   r   kwargsrz   s      r   r7   zCloudinaryImage.__init__C      ot-k	Y`kdjkr   r9   rm   rn   ro   r7   r   r   s   @r   ra  ra  B      l lr   ra  c                         e Zd Zd fd	Z xZS )CloudinaryVideoc                 2    t        t        | 
  d|dd| y )Nr  rc  r   )rw   rj  r7   rd  s      r   r7   zCloudinaryVideo.__init__H  rf  r   r9   rg  r   s   @r   rj  rj  G  rh  r   rj  )D
__future__r   rq   loggingr   r   r?   r  r   mathr   certifisixr   r   	getLoggerr   StreamHandlerch	Formatter	formattersetFormatter
addHandlerr   r	   cloudinary.exceptionsr
   cloudinary.cacher   cloudinary.http_clientr   cloudinary.compatr   r   r   r   whereCERT_KWARGSCF_SHARED_CDNOLD_AKAMAI_SHARED_CDNAKAMAI_SHARED_CDN
SHARED_CDNr  rv   API_VERSIONVERSIONr  r)   _USER_PLATFORM_DETAILSr   r   r   r.   ABCMetaobjectr0   rt   r   r   r   r   cloudinary.searchr   cloudinary.search_foldersr   r   ra  rj  r   r   r   <module>r     s   & 
   	 	    :			<	(WGTU	 	    "   . 9 - 0 - !
 03 ( 
[

HJ0B0B>CS0T#UV '..w8NO
 06 s{{H! H! H!V&BZ &BR (
 | % 3 N	B N	B N	Bbl( l
l( lr   