Ë
    qûàgh=  ã                   ó¶   — d Z ddl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mZmZ ddlmZ ddlmZ 	 ddlZdZ G d
„ de«      Zy# e$ r d	ZY Œw xY w)a�	  
Sync Media to S3
================

Django command that scans all files in your settings.MEDIA_ROOT and
settings.STATIC_ROOT folders and uploads them to S3 with the same directory
structure.

This command can optionally do the following but it is off by default:
* gzip compress any CSS and Javascript files it finds and adds the appropriate
  'Content-Encoding' header.
* set a far future 'Expires' header for optimal caching.
* upload only media or static files.
* use any other provider compatible with Amazon S3.
* set other than 'public-read' ACL.

Note: This script requires the Python boto library and valid Amazon Web
Services API keys.

Required settings.py variables:
AWS_ACCESS_KEY_ID = ''
AWS_SECRET_ACCESS_KEY = ''
AWS_BUCKET_NAME = ''

When you call this command with the `--renamegzip` param, it will add
the '.gz' extension to the file name. But Safari just doesn't recognize
'.gz' files and your site won't work on it! To fix this problem, you can
set any other extension (like .jgz) in the `SYNC_S3_RENAME_GZIP_EXT`
variable.

Command options are:
  -p PREFIX, --prefix=PREFIX
                        The prefix to prepend to the path on S3.
  --gzip                Enables gzipping CSS and Javascript files.
  --expires             Enables setting a far future expires header.
  --force               Skip the file mtime check to force upload of all
                        files.
  --filter-list         Override default directory and file exclusion
                        filters. (enter as comma separated line)
  --renamegzip          Enables renaming of gzipped files by appending '.gz'.
                        to the original file name. This way your original
                        assets will not be replaced by the gzipped ones.
                        You can change the extension setting the
                        `SYNC_S3_RENAME_GZIP_EXT` var in your settings.py
                        file.
  --invalidate          Invalidates the objects in CloudFront after uploading
                        stuff to s3.
  --media-only          Only MEDIA_ROOT files will be uploaded to S3.
  --static-only         Only STATIC_ROOT files will be uploaded to S3.
  --s3host              Override default s3 host.
  --acl                 Override default ACL settings ('public-read' if
                        settings.AWS_DEFAULT_ACL is not defined).

TODO:
 * Use fnmatch (or regex) to allow more complex FILTER_LIST rules.

é    N)ÚList)Úsettings)ÚBaseCommandÚCommandError)ÚStringIO)ÚsignalcommandTFc                   ó”   ‡ — e Zd ZdZdZdZdZdZdZg d¢Z	dZ
g ZdZdZdZdZdZˆ fd„Zed	„ «       Zd
„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zˆ xZS )ÚCommandÚ )z	.DS_Storez.svnz.hgz.gitz	Thumbs.db)ztext/csszapplication/javascriptzapplication/x-javascriptztext/javascriptr   zSSyncs the complete MEDIA_ROOT structure and files to S3 into the given bucket name.Úbucket_nameTc           
      óˆ  •— t         ‰| �  |«       |j                  dddt        t        dd«      d¬«       |j                  dd	d
d¬«       |j                  ddt        t        dd«      d¬«       |j                  ddt        t        dd«      d¬«       |j                  ddddd¬«       |j                  ddddd¬«       |j                  ddd dd!¬«       |j                  d"dd#dd$¬«       |j                  d%d&d'dd(¬)«       |j                  d*d+ddd,¬-«       |j                  d.d/ddd0¬-«       |j                  d1d2ddd3¬-«       y )4Nz-pz--prefixÚprefixÚSYNC_S3_PREFIXr   z(The prefix to prepend to the path on S3.)ÚdestÚdefaultÚhelpz-dz--dirÚdirz#Custom static root directory to use)r   r   z--s3hostÚs3hostÚAWS_S3_HOSTz;The s3 host (enables connecting to other providers/regions)z--aclÚaclÚAWS_DEFAULT_ACLzpublic-readz.Enables to override default acl (public-read).z--gzipÚ
store_trueÚgzipFz*Enables gzipping CSS and Javascript files.)Úactionr   r   r   z--renamegzipÚ
renamegzipzJEnables renaming of gzipped assets to have '.gz' appended to the filename.z	--expiresÚexpiresz,Enables setting a far future expires header.z--forceÚforcez7Skip the file mtime check to force upload of all files.z--filter-listÚfilter_listÚstorezVOverride default directory and file exclusion filters. (enter as comma seperated line))r   r   r   r   z--invalidateÚ
invalidatez0Invalidates the associated objects in CloudFront)r   r   r   r   z--media-onlyÚ
media_onlyz,Only MEDIA_ROOT files will be uploaded to S3z--static-onlyÚstatic_onlyz-Only STATIC_ROOT files will be uploaded to S3)ÚsuperÚadd_argumentsÚadd_argumentÚgetattrr   )ÚselfÚparserÚ	__class__s     €úk/var/www/skyplay_api_hub/venv/lib/python3.12/site-packages/django_extensions/management/commands/sync_s3.pyr$   zCommand.add_argumentsl   sÀ  ø€ Ü‰Ñ˜fÔ%Ø×ÑØ�*ØÜœHÐ&6¸Ó;Ø;ð	 	ô 	
ð 	×ÑØ�'ØØ6ð 	ô 	
ð
 	×ÑØØÜœH m°RÓ8ØNð	 	ô 	
ð 	×ÑØØÜœHÐ&7¸ÓGØAð	 	ô 	
ð 	×ÑØØ f°eØ=ð 	ô 	
ð
 	×ÑØØ l¸EØ]ð 	ô 	
ð
 	×ÑØØ i¸Ø?ð 	ô 	
ð
 	×ÑØØ g°uØJð 	ô 	
ð
 	×ÑØ -Ø BØið 	ô 	
ð
 	×ÑØ °uØØCð 	ô 	
ð
 	×ÑØ °rØØ?ð 	ô 	
ð
 	×ÑØ -¸ØØ@ð 	õ 	
ó    c                 ó¼  — t         st        d«      ‚t        t        d«      rt        t        d«      st        d«      ‚t        j                  | _        t        j
                  | _        t        t        d«      st        d«      ‚t        j                  st        d«      ‚t        j                  | _        t        t        d«      st        d	«      ‚t        j                  st        d	«      ‚t        t        d
d«      | _	        t        t        dd«      | _
        |d   | _        |d   | _        |d   | _        |d   | _        |d   | _        |d   | _        |d   | _        |d   | _        |d   | _        |d   | _        t        t        d| j*                  «      | _        |d   }|r|j-                  d«      | _        |d   | _        |d   | _        | j.                  r| j0                  rt        d«      ‚| j.                  rt        j                  g| _        ng| j0                  rt        j2                  g| _        nD| j$                  r| j$                  g| _        n%t        j                  t        j2                  g| _        | j5                  «        | j"                  r| j7                  «        t9        d«       t9        d| j:                  z  «       t9        d| j<                  z  «       y ) Nz>Please install the 'boto' Python library. ($ pip install boto)ÚAWS_ACCESS_KEY_IDÚAWS_SECRET_ACCESS_KEYzeMissing AWS keys from settings file.  Please supply both AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY.ÚAWS_BUCKET_NAMEz]Missing bucket name from settings file. Please add the AWS_BUCKET_NAME to your settings file.z AWS_BUCKET_NAME cannot be empty.Ú
MEDIA_ROOTz(MEDIA_ROOT must be set in your settings.ÚAWS_CLOUDFRONT_DISTRIBUTIONr   ÚSYNC_S3_RENAME_GZIP_EXTz.gzÚ	verbosityr   r   r   r   r   r    r   r   r   ÚFILTER_LISTr   ú,r!   r"   zMCan't use --media-only and --static-only together. Better not use anything...z%d files uploaded.z%d files skipped.)ÚHAS_BOTOr   Úhasattrr   r-   r.   r/   r0   r&   r1   r2   r3   r   Údo_gzipÚrename_gzipÚ
do_expiresÚdo_forcer    ÚDIRECTORIESr   Údefault_aclr4   Úsplitr!   r"   ÚSTATIC_ROOTÚsync_s3Úinvalidate_objects_cfÚprintÚupload_countÚ
skip_count)r'   ÚargsÚoptionsr   s       r*   ÚhandlezCommand.handle®   s�  € åÜÐ_Ó`Ð`ô ”xÐ!4Ô5¼WÄXÐOfÔ=gÜð   Gó  Hð  Hä%-×%?Ñ%?ˆDÔ"Ü)1×)GÑ)GˆDÔ&ä”xÐ!2Ô3ÜÐ~ÓÐä×+Ò+Ü"Ð#EÓFÐFÜ'×7Ñ7ˆÔä”x Ô.ÜÐIÓJÐJä×&Ò&Ü"Ð#MÓNÐNä+2´8Ð=ZÐ\^Ó+_ˆÔ(ô ”HÐ7¸Ó?ð 	Ô$ð ! Ñ-ˆŒØ˜hÑ'ˆŒØ˜v‘ˆŒØ" <Ñ0ˆÔØ! )Ñ,ˆŒØ Ñ(ˆŒØ! ,Ñ/ˆŒØ" 5™>ˆÔØ˜hÑ'ˆŒØ" 5™>ˆÔÜ"¤8¨]¸D×<LÑ<LÓMˆÔØ˜mÑ,ˆÙð  +×0Ñ0°Ó5ˆDÔà! ,Ñ/ˆŒØ" =Ñ1ˆÔà�?Š?˜t×/Ò/ÜÐnÓoÐoØ�_Š_Ü (× 3Ñ 3Ð4ˆDÕØ×ÒÜ (× 4Ñ 4Ð5ˆDÕØ×ÒØ $× 0Ñ 0Ð1ˆDÕä (× 3Ñ 3´X×5IÑ5IÐJˆDÔð 	�‰Œð �?Š?Ø×&Ñ&Ô(äˆbŒ	ÜÐ" T×%6Ñ%6Ñ6Ô7ÜÐ! D§O¡OÑ3Õ4r+   c                 óV   — t        j                  | j                  | j                  «      S )z'Return an open connection to CloudFront)ÚbotoÚconnect_cloudfrontr-   r.   )r'   s    r*   Úopen_cfzCommand.open_cfø   s(   € ä×&Ñ&Ø×"Ñ" D×$>Ñ$>ó@ð 	@r+   c                 ó  — | j                   st        d«      ‚d}| j                  «       }| j                  }t	        dt        |«      |«      D �cg c]
  }||||z    ‘Œ }}|D ]  }|j                  | j                   |«       Œ  yc c}w )z8Split the invalidation request in groups of 1000 objectszrAn object invalidation was requested but the variable AWS_CLOUDFRONT_DISTRIBUTION is not present in your settings.iè  r   N)r1   r   rK   Úuploaded_filesÚrangeÚlenÚcreate_invalidation_request)r'   ÚchunkÚconnÚobjsÚiÚchunksÚpathss          r*   rA   zCommand.invalidate_objects_cfý   sœ   € à×/Ò/ÜðOóPð Pð ˆð �|‰|‹~ˆð ×"Ñ"ˆÜ-2°1´c¸$³iÀÓ-GÖH¨�$�q˜˜U™Ò#ÐHˆÐHð ò 	9ˆEØ×,Ñ,Ø×0Ñ0°%õ9ñ	9ùò Is   ÁBc                 óÌ   — | j                  «       \  }}| j                  D ]B  }t        j                  |«      D ](  \  }}}| j	                  ||| j
                  |f|||«       Œ* ŒD y)z7Walk the media/static directories and syncs files to S3N)Úopen_s3r<   ÚosÚwalkÚ	upload_s3r/   )r'   ÚbucketÚkeyÚ	directoryÚrootÚdirsÚfiless          r*   r@   zCommand.sync_s3  sl   € à—l‘l“n‰ˆ�Ø×)Ñ)ò 	bˆIÜ%'§W¡W¨YÓ%7ò bÑ!��d˜EØ—‘ ¨¨T×-AÑ-AÀ9ÐMÈtÐUZÐ\`Õañbñ	br+   c                 ó¨   — t        «       }t        j                  dd|¬«      }|j                  |«       |j	                  «        |j                  «       S )zGzip a given string.Úwbé   )ÚmodeÚcompresslevelÚfileobj)r   r   ÚGzipFileÚwriteÚcloseÚgetvalue)r'   ÚsÚzbufÚzfiles       r*   Úcompress_stringzCommand.compress_string  s;   € ä‹zˆÜ—‘ 4°qÀ$ÔGˆØ�‰�AŒØ�‰ŒØ�}‰}‹Ðr+   c                 ó@   — i }| j                   r| j                   |d<   |S )z"Return connection kwargs as a dictÚhost)r   )r'   Úkwargss     r*   Úget_s3connection_kwargszCommand.get_s3connection_kwargs#  s    € àˆØ�;Š;Ø!Ÿ[™[ˆF�6‰NØˆr+   c                 ó~  — t        j                  | j                  | j                  fi | j	                  «       ¤Ž}	 |j                  | j                  «      }|t         j                  j                  j                  |«      fS # t         j                  j                  $ r |j                  | j                  «      }Y Œew xY w)z.Open connection to S3 returning bucket and key)rI   Ú
connect_s3r-   r.   rs   Ú
get_bucketr/   Ú	exceptionÚS3ResponseErrorÚcreate_bucketÚs3r]   ÚKey)r'   rR   r\   s      r*   rX   zCommand.open_s3*  s�   € ä�‰Ø×"Ñ"Ø×&Ñ&ñ.ð ×*Ñ*Ó,ñ.ˆð	>Ø—_‘_ T×%9Ñ%9Ó:ˆFð ”t—w‘w—{‘{—‘ vÓ.Ð.Ð.øô �~‰~×-Ñ-ò 	>Ø×'Ñ'¨×(<Ñ(<Ó=ŠFð	>ús   »B Â8B<Â;B<c           
      óî  — |\  }}}}t         j                  j                  |«      | j                  v r1t         j                  j	                  |«      | j
                  v r|d d …= y |j                  t         j                  j                  «      s|t         j                  j                  z   }|D �]v  }	i }
|	| j                  v rŒt         j                  j                  ||	«      }t         j                  j                  |«      rŒU|t        |«      d  }| j                  r| j                  ›d|›�}| j                  s»|j                  |«      }|r¨t        j                  t        j                   |j"                  d«      dd Ž }t        j                  j%                  t        j&                  |«      j(                  «      }||k  r4| xj*                  dz  c_        | j,                  dkD  rt/        d|z  «       �ŒG| j,                  dkD  rt/        d|z  «       t1        j2                  |«      d   }|r||
d<   nd	|
d<   t5        |d
«      }t        j6                  |j9                  «       «      j:                  }|j=                  «       }| j>                  rt|dkD  ro|| j@                  v ra| jC                  |«      }| jD                  r|›d| jF                  ›�}d|
d<   | j,                  dkD  rt/        d|dz  t        |«      dz  fz  «       | jH                  r²dtJ        jL                  jO                  t        jP                  t        j                  jS                  «       t        jT                  d¬«      z   jW                  «       «      «      z  |
d<   ddz  |
d<   | j,                  dkD  r"t/        d|
d   z  «       t/        d|
d   z  «       	 ||_,        |j[                  ||
d| j\                  ¬«       | xj^                  dz  c_/        | j`                  jc                  |«       |jm                  «        �Œy y # td        jf                  jh                  $ r}t/        d|z  «       Y d }~ŒDd }~wtj        $ r}t/        |«       ‚ d }~ww xY w)Nú/z%a, %d %b %Y %H:%M:%S %Zr   rd   é   z6File %s hasn't been modified since last being uploadedzUploading %s...zContent-Typezapplication/octet-streamÚrbi   ú.r   zContent-Encodingz	gzipped: %dk to %dkz%s GMTiÚ  )ÚdaysÚExpiresz
max-age %di gÂzCache-Controlz	expires: %sz	cache-control: %sT)ÚreplaceÚpolicyz
Failed: %s)7rY   ÚpathÚbasenamer4   Údirnamer<   ÚendswithÚsepÚjoinÚisdirrO   r   r;   Úget_keyÚdatetimeÚtimeÚstrptimeÚlast_modifiedÚutcfromtimestampÚstatÚst_mtimerD   r3   rB   Ú	mimetypesÚ
guess_typeÚopenÚfstatÚfilenoÚst_sizeÚreadr8   ÚGZIP_CONTENT_TYPESro   r9   r2   r:   ÚemailÚUtilsÚ
formatdateÚmktimeÚnowÚ	timedeltaÚ	timetupleÚnameÚset_contents_from_stringr=   rC   rM   ÚappendrI   rw   ÚS3CreateErrorÚ	Exceptionrj   )r'   Úargr‡   Únamesr`   r\   r]   r   Úroot_dirÚfileÚheadersÚfilenameÚfile_keyÚs3_keyÚs3_datetimeÚlocal_datetimeÚcontent_typeÚfile_objÚ	file_sizeÚfiledataÚes                        r*   r[   zCommand.upload_s36  sÿ  € Ø-0Ñ*ˆ��[ (ô �7‰7×Ñ˜GÓ$¨×(8Ñ(8Ñ8¼R¿W¹W¿_¹_ÈWÓ=UÐY]×YiÑYiÑ=ià’Q�Øð × Ñ ¤§¡§¡Ô-Ø¤"§'¡'§+¡+Ñ-ˆHàó M	ˆDØˆGà�t×'Ñ'Ñ'Øä—w‘w—|‘| G¨TÓ2ˆHÜ�w‰w�}‰}˜XÔ&Øà¤ H£ Ð/ˆHØ�{Š{Ø&*§k£k±8Ð<�ð —=’=ØŸ™¨Ó1�ÙÜ"*×"3Ñ"3´T·]±]Ø×,Ñ,Ð.Hó6JØJKÈAð6Oð #P�Kä%-×%6Ñ%6×%GÑ%GÜŸ™ Ó)×2Ñ2ó&4�Nà%¨Ò3ØŸš¨1Ñ,�ØŸ>™>¨AÒ-Ü!Ð"ZÐ]eÑ"eÔfÙ ð �~‰~ Ò!ÜÐ'¨(Ñ2Ô3ä$×/Ñ/°Ó9¸!Ñ<ˆLÙØ*6�˜Ò'à*D�˜Ñ'ä˜H dÓ+ˆHÜŸ™ §¡Ó!2Ó3×;Ñ;ˆIØ—}‘}“ˆHØ�|Š|ð ˜tÒ#¨¸×8OÑ8OÑ(OØ#×3Ñ3°HÓ=�HØ×'Ò'ò
 % d×&BÒ&Bð$D˜à28�GÐ.Ñ/Ø—~‘~¨Ò)ÜÐ5¸ÀTÑ9IÌ3ÈxË=Ð[_ÑK_Ð8`Ñ`ÔaØ�Šà%-´·±×1GÑ1GÌÏÉÔU]×UfÑUf×UjÑUjÓUlÔow÷  pBñ  pBð  HOô  pPñ  VP÷  U[ñ  U[ó  U]ó  I^ó  2_ñ  &`�˜	Ñ"à+7Ð;NÑ+O�˜Ñ(Ø—>‘> AÒ%Ü˜/¨G°IÑ,>Ñ>Ô?ÜÐ/°'¸/Ñ2JÑJÔKð5Ø#�”Ø×,Ñ,¨X°wÈØ48×4DÑ4Dð -ô Fð ×!Ò! QÑ&Õ!Ø×#Ñ#×*Ñ*¨8Ô4à�N‰NÖñ[M	øôH —>‘>×/Ñ/ò (Ü�l QÑ&×'Ñ'ûÜò Ü�a”Øûðús$   Î=&P'Ð'Q4ÑQÑQ4Ñ#Q/Ñ/Q4)Ú__name__Ú
__module__Ú__qualname__r-   r.   r/   r1   r2   r<   r4   r›   rM   rC   rD   r   rE   Úcan_import_settingsr$   r   rG   rK   rA   r@   ro   rs   rX   r[   Ú__classcell__)r)   s   @r*   r
   r
   R   s—   ø„ àÐØÐØ€OØ"$ÐØ Ðà€KÚC€KðÐð €NØ€LØ€Jà`€DØ€DàÐô@
ðD ñG5ó ðG5òR@ò
9ò.bòòò
/öZr+   r
   )Ú__doc__r�   rœ   r   r”   rY   rŽ   Útypingr   Údjango.confr   Údjango.core.management.baser   r   Úior   Ú"django_extensions.management.utilsr   rI   r6   ÚImportErrorr
   © r+   r*   ú<module>rÄ      sa   ðñ8ór Û Û Û Û 	Û Ý å  ß AÝ å <ðÛð €Hô~ˆkõ ~øð ò Ø‚Hðús   ¼A ÁAÁA