o
    ?eQj                     @   s  d Z ddlmZ 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
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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 ddlmZ dd	lm Z  ej!d d
kr}d>ddZ"nddl#m"Z" dd Z$d?ddZ%								d@ddZ&dd Z'dAddZ(dBddZ)dCd d!Z*G d"d# d#e+Z,d$d% Z-G d&d' d'e+Z.d(d) Z/i a0da1e2 Z3da4e5 Z6da7e8 Z9d*d+ Z:d,d- Z;d.d/ Z<d0d1 Z=d2d3 Z>G d4d5 d5e+Z?G d6d7 d7e?Z@d>d8d9ZAd:d; ZBG d<d= d=e?ZCdS )Dz(Utilities for file download and caching.    )abstractmethod)closingN)tensor)urlopen)
tf_inspect)Progbar)path_to_string   c                 C   s`   ddd}t | |}t|d}|||dD ]}|| qW d   dS 1 s)w   Y  dS )a  Replacement for `urlretrieve` for Python 2.

    Under Python 2, `urlretrieve` relies on `FancyURLopener` from legacy
    `urllib` module, known to have issues with proxy management.

    Args:
        url: url to retrieve.
        filename: where to store the retrieved data locally.
        reporthook: a hook function that will be called once on establishment of
          the network connection and once after each block read thereafter. The
          hook will be passed three arguments; a count of blocks transferred so
          far, a block size in bytes, and the total size of the file.
        data: `data` argument passed to `urlopen`.
        Nc                 s   sf    |   d}d}|d urt| }d}	 | |}|d7 }|d ur*|||| |r0|V  nd S q)NzContent-Lengthr   T   )infogetintstripread)response
chunk_size
reporthookcontent_type
total_sizecountchunk r   i/home/www/facesmatcher.com/pyenv/lib/python3.10/site-packages/tensorflow/python/keras/utils/data_utils.py
chunk_read@   s   
zurlretrieve.<locals>.chunk_readwb)r   )r
   N)r   openwrite)urlfilenamer   datar   r   fdr   r   r   r   urlretrieve0   s   

"r#   )r#   c                 C   sJ   t tttttf}t| tjt	j
f| rdS t| p$t| tp$t| tjS )z'Check if `x` is a Keras generator type.F)strlisttupledictset	frozenset
isinstancer   ZTensornpZndarrayr   isgeneratorSequencetypingIterator)xZbuiltin_iteratorsr   r   r   is_generator_or_sequenceX   s   

r1   .autoc                 C   s  |du rdS |dkrddg}t |tr|g}t| } t|}|D ]^}|dkr,tj}tj}|dkr6tj}tj}|| r~|| 5}z|	| W n# tj
ttfyi   tj|rhtj|rct|  t|  w W d    dS 1 svw   Y   dS q dS )a6  Extracts an archive if it matches tar, tar.gz, tar.bz, or zip formats.

  Args:
      file_path: path to the archive file
      path: path to extract the archive file
      archive_format: Archive format to try for extracting the file.
          Options are 'auto', 'tar', 'zip', and None.
          'tar' includes tar, tar.gz, and tar.bz files.
          The default 'auto' is ['tar', 'zip'].
          None or an empty list will return no matches found.

  Returns:
      True if a match was found and an archive extraction was completed,
      False otherwise.
  NFr3   tarzipT)r*   r$   r   tarfiler   
is_tarfilezipfileZipFile
is_zipfile
extractallTarErrorRuntimeErrorKeyboardInterruptospathexistsisfileremoveshutilrmtree)	file_pathr@   archive_formatZarchive_typeZopen_fnZis_match_fnarchiver   r   r   _extract_archiveb   sD   






rI   Fdatasetsc
              
      s  |	du rt jt jdd}	|dur|du r|}d}t j|	}
t |
t js/t jdd}
t j|
|}t| t| } |rLt j|| }|d }nt j|| }d}t j|ru|durtt	|||dstt
d	| d
 | d  d}nd}|rt
d| G dd dt  fdd}d}z<zt||| W n1 tjjy } zt|||j|jd}~w tjjy } zt|||j|jd}~ww W n ttfy } zt j|rt |  d}~ww d _|rt j|st||dd |S |rt||| |S )a  Downloads a file from a URL if it not already in the cache.

  By default the file at the url `origin` is downloaded to the
  cache_dir `~/.keras`, placed in the cache_subdir `datasets`,
  and given the filename `fname`. The final location of a file
  `example.txt` would therefore be `~/.keras/datasets/example.txt`.

  Files in tar, tar.gz, tar.bz, and zip formats can also be extracted.
  Passing a hash will verify the file after download. The command line
  programs `shasum` and `sha256sum` can compute the hash.

  Example:

  ```python
  path_to_downloaded_file = tf.keras.utils.get_file(
      "flower_photos",
      "https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz",
      untar=True)
  ```

  Args:
      fname: Name of the file. If an absolute path `/path/to/file.txt` is
          specified the file will be saved at that location.
      origin: Original URL of the file.
      untar: Deprecated in favor of `extract` argument.
          boolean, whether the file should be decompressed
      md5_hash: Deprecated in favor of `file_hash` argument.
          md5 hash of the file for verification
      file_hash: The expected hash string of the file after download.
          The sha256 and md5 hash algorithms are both supported.
      cache_subdir: Subdirectory under the Keras cache dir where the file is
          saved. If an absolute path `/path/to/folder` is
          specified the file will be saved at that location.
      hash_algorithm: Select the hash algorithm to verify the file.
          options are `'md5'`, `'sha256'`, and `'auto'`.
          The default 'auto' detects the hash algorithm in use.
      extract: True tries extracting the file as an Archive, like tar or zip.
      archive_format: Archive format to try for extracting the file.
          Options are `'auto'`, `'tar'`, `'zip'`, and `None`.
          `'tar'` includes tar, tar.gz, and tar.bz files.
          The default `'auto'` corresponds to `['tar', 'zip']`.
          None or an empty list will return no matches found.
      cache_dir: Location to store cached files, when None it
          defaults to the default directory `~/.keras/`.

  Returns:
      Path to the downloaded file
  N~z.kerasmd5z/tmpz.tar.gzF)	algorithmzNA local file was found, but it seems to be incomplete or outdated because the z0 file hash does not match the original value of z! so we will re-download the data.TzDownloading data fromc                   @   s   e Zd ZdZdS )z!get_file.<locals>.ProgressTrackerN)__name__
__module____qualname__progbarr   r   r   r   ProgressTracker   s    rR   c                    s8    j d u r|dkrd }t| _ d S  j | |  d S )Nr   )rQ   r   update)r   
block_sizer   rR   r   r   dl_progress   s
   
zget_file.<locals>.dl_progressz!URL fetch failure on {}: {} -- {}r4   )rG   )r?   r@   join
expanduseraccessW_OK_makedirs_exist_okr   rA   validate_fileprintobjectr#   urlliberror	HTTPError	ExceptionformatcodemsgURLErrorerrnoreasonr>   rC   rQ   rI   )fnameoriginZuntarZmd5_hash	file_hashZcache_subdirZhash_algorithmextractrG   	cache_dirZdatadir_basedatadirZuntar_fpathfpathdownloadrV   	error_msger   rU   r   get_file   sz   :


rs   c                 C   s   t j| dd d S )NT)exist_ok)r?   makedirs)rn   r   r   r   r[     s   r[   c                 C   s<   | dkrt  S | dkr|durt|dkrt  S t  S )z+Returns hash algorithm as hashlib function.sha256r3   N@   )hashlibrv   lenrL   )rM   rk   r   r   r   _resolve_hasher  s
   rz   rv     c                    st   t |tr
t|}n|}t| dt fdddD ]}|| qW d   | S 1 s1w   Y  | S )a  Calculates a file sha256 or md5 hash.

  Example:

  ```python
  _hash_file('/path/to/file.zip')
  'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'
  ```

  Args:
      fpath: path to the file being validated
      algorithm: hash algorithm, one of `'auto'`, `'sha256'`, or `'md5'`.
          The default `'auto'` detects the hash algorithm in use.
      chunk_size: Bytes to read at a time, important for large files.

  Returns:
      The file hash
  rbc                      s
     S N)r   r   r   Z
fpath_filer   r   <lambda>?  s   
 z_hash_file.<locals>.<lambda>    N)r*   r$   rz   r   iterrS   	hexdigest)ro   rM   r   hasherr   r   r~   r   
_hash_file&  s   


r   c                 C   s*   t ||}tt| ||t|krdS dS )a  Validates a file against a sha256 or md5 hash.

  Args:
      fpath: path to the file being validated
      file_hash:  The expected hash string of the file.
          The sha256 and md5 hash algorithms are both supported.
      algorithm: Hash algorithm, one of 'auto', 'sha256', or 'md5'.
          The default 'auto' detects the hash algorithm in use.
      chunk_size: Bytes to read at a time, important for large files.

  Returns:
      Whether the file is valid
  TF)rz   r$   r   )ro   rk   rM   r   r   r   r   r   r\   E  s   
r\   c                   @   s0   e Zd ZdZdd Zdd Zdd Zdd	 Zd
S )ThreadsafeIterzEWrap an iterator with a lock and propagate exceptions to all threads.c                 C   s   || _ t | _d | _d S r}   )it	threadingLocklock
_exception)selfr   r   r   r   __init__^  s   

	zThreadsafeIter.__init__c                 C   s   | S r}   r   r   r   r   r   __iter__k  s   zThreadsafeIter.__iter__c                 C   s   |   S r}   )__next__r   r   r   r   nextn  s   zThreadsafeIter.nextc                 C   sd   | j % | jr
| jzt| jW W  d    S  ty' } z|| _ d }~ww 1 s+w   Y  d S r}   )r   r   r   r   rb   )r   rr   r   r   r   r   q  s   
zThreadsafeIter.__next__N)rN   rO   rP   __doc__r   r   r   r   r   r   r   r   r   [  s    r   c                       t   fdd}|S )Nc                     s   t  | i |S r}   )r   )akwfr   r   g  s   zthreadsafe_generator.<locals>.g	functoolswraps)r   r   r   r   r   threadsafe_generator}  s   r   c                   @   s8   e Zd ZdZedd Zedd Zdd Zdd	 Zd
S )r-   a1  Base object for fitting to a sequence of data, such as a dataset.

  Every `Sequence` must implement the `__getitem__` and the `__len__` methods.
  If you want to modify your dataset between epochs you may implement
  `on_epoch_end`.
  The method `__getitem__` should return a complete batch.

  Notes:

  `Sequence` are a safer way to do multiprocessing. This structure guarantees
  that the network will only train once
   on each sample per epoch which is not the case with generators.

  Examples:

  ```python
  from skimage.io import imread
  from skimage.transform import resize
  import numpy as np
  import math

  # Here, `x_set` is list of path to the images
  # and `y_set` are the associated classes.

  class CIFAR10Sequence(Sequence):

      def __init__(self, x_set, y_set, batch_size):
          self.x, self.y = x_set, y_set
          self.batch_size = batch_size

      def __len__(self):
          return math.ceil(len(self.x) / self.batch_size)

      def __getitem__(self, idx):
          batch_x = self.x[idx * self.batch_size:(idx + 1) *
          self.batch_size]
          batch_y = self.y[idx * self.batch_size:(idx + 1) *
          self.batch_size]

          return np.array([
              resize(imread(file_name), (200, 200))
                 for file_name in batch_x]), np.array(batch_y)
  ```
  c                 C      t )zGets batch at position `index`.

    Args:
        index: position of the batch in the Sequence.

    Returns:
        A batch
    NotImplementedError)r   indexr   r   r   __getitem__     
zSequence.__getitem__c                 C   r   )zbNumber of batch in the Sequence.

    Returns:
        The number of batches in the Sequence.
    r   r   r   r   r   __len__  s   zSequence.__len__c                 C   s   dS )z-Method called at the end of every epoch.
    Nr   r   r   r   r   on_epoch_end     zSequence.on_epoch_endc                 #   s,     fddt t D D ]}|V  qdS )z2Create a generator that iterate over the Sequence.c                 3   s    | ]} | V  qd S r}   r   ).0ir   r   r   	<genexpr>  s    z$Sequence.__iter__.<locals>.<genexpr>N)rangery   )r   itemr   r   r   r     s   zSequence.__iter__N)	rN   rO   rP   r   r   r   r   r   r   r   r   r   r   r-     s    -

r-   c                 c   s    	 | D ]}|V  qq)zIterates indefinitely over a Sequence.

  Args:
    seq: `Sequence` instance.

  Yields:
    Batches of data from the `Sequence`.
  r   )seqr   r   r   r   iter_sequence_infinite  s
   	r   c                    r   )Nc                     sH   t  td}a | i |}|a|W  d    S 1 sw   Y  d S )NT)_FORCE_THREADPOOL_LOCK_FORCE_THREADPOOL)argskwargsZold_force_threadpooloutr   r   r   wrapped  s   
$z.dont_use_multiprocessing_pool.<locals>.wrappedr   )r   r   r   r   r   dont_use_multiprocessing_pool  s   r   c                 C   s   | rt rtjjS tjS r}   )r   multiprocessingdummyZPool)use_multiprocessingr   r   r   get_pool_class  s   r   c                   C   s   t du rt a t S )z,Lazily create the queue to track worker ids.N)_WORKER_ID_QUEUEr   Queuer   r   r   r   get_worker_id_queue  s   r   c                 C   s   | a d S r}   _SHARED_SEQUENCES)seqsr   r   r   	init_pool  s   r   c                 C   s   t |  | S )aQ  Get the value from the Sequence `uid` at index `i`.

  To allow multiple Sequences to be used at the same time, we use `uid` to
  get a specific one. A single Sequence would cause the validation to
  overwrite the training Sequence.

  Args:
      uid: int, Sequence identifier
      i: index

  Returns:
      The value at index `i`.
  r   )uidr   r   r   r   	get_index  s   r   c                   @   sl   e Zd ZdZ	dddZdd Zdd	d
Zdd ZdddZdd Z	e
dd Ze
dd Ze
dd ZdS )SequenceEnqueuera  Base class to enqueue inputs.

  The task of an Enqueuer is to use parallelism to speed up preprocessing.
  This is done with processes or threads.

  Example:

  ```python
      enqueuer = SequenceEnqueuer(...)
      enqueuer.start()
      datas = enqueuer.get()
      for data in datas:
          # Use the inputs; training, evaluating, predicting.
          # ... stop sometime.
      enqueuer.stop()
  ```

  The `enqueuer.get()` should be an infinite stream of datas.
  Fc                 C   s   || _ || _td u rztddaW n ty   daY nw tttr+t| _td7 ant	  tj
| _t j
d7  _
W d    n1 sEw   Y  d| _d | _d | _d | _d | _d S )Nr   r   r   )sequencer   _SEQUENCE_COUNTERr   ValueOSErrorr*   r   r   Zget_lockvalueworkersexecutor_fnqueue
run_threadstop_signal)r   r   r   r   r   r   r   8  s(   



zSequenceEnqueuer.__init__c                 C   s   | j d uo
| j   S r}   )r   is_setr   r   r   r   
is_runningV  s   zSequenceEnqueuer.is_runningr   
   c                    sd   | j r
|  | _n fdd| _ | _t|| _t | _tj	| j
d| _d| j_| j  dS )zStarts the handler's workers.

    Args:
        workers: Number of workers.
        max_queue_size: queue size
            (when full, workers could block on `put()`)
    c                    s   t d S )NF)r   )_r   r   r   r   e  s    z(SequenceEnqueuer.start.<locals>.<lambda>)targetTN)r   _get_executor_initr   r   r   r   r   Eventr   Thread_runr   daemonstart)r   r   Zmax_queue_sizer   r   r   r   Y  s   
zSequenceEnqueuer.startc                 C   s   | j t| j< dS )z&Sends current Iterable to all workers.N)r   r   r   r   r   r   r   _send_sequencem  s   zSequenceEnqueuer._send_sequenceNc                 C   sl   | j   | jj | jj  d| j_| jj  W d   n1 s$w   Y  | j	| dt
| j< dS )zStops running threads and wait for them to exit, if necessary.

    Should be called by the same thread which called `start()`.

    Args:
        timeout: maximum time to wait on `thread.join()`
    r   N)r   r(   r   mutexclearunfinished_tasksnot_fullnotifyr   rW   r   r   )r   timeoutr   r   r   stopr  s   

zSequenceEnqueuer.stopc                 C   s   |   r
|   d S d S r}   )r   r   r   r   r   r   __del__  s   zSequenceEnqueuer.__del__c                 C   r   )?Submits request to the executor and queue the `Future` objects.r   r   r   r   r   r     r   zSequenceEnqueuer._runc                 C   r   )Gets the Pool initializer for multiprocessing.

    Args:
        workers: Number of workers.

    Returns:
        Function, a Function to initialize the pool
    r   r   r   r   r   r   r     r   z#SequenceEnqueuer._get_executor_initc                 C   r   )zCreates a generator to extract data from the queue.

    Skip the data if it is `None`.
    # Returns
        Generator yielding tuples `(inputs, targets)`
            or `(inputs, targets, sample_weights)`.
    r   r   r   r   r   r     s   	zSequenceEnqueuer.get)F)r   r   r}   )rN   rO   rP   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   #  s    




r   c                       sB   e Zd ZdZd fdd	Zdd Zdd Zd	d
 Zdd Z  Z	S )OrderedEnqueuera  Builds a Enqueuer from a Sequence.

  Args:
      sequence: A `tf.keras.utils.data_utils.Sequence` object.
      use_multiprocessing: use multiprocessing if True, otherwise threading
      shuffle: whether to shuffle the data at the beginning of each epoch
  Fc                       t t| || || _d S r}   )superr   r   shuffle)r   r   r   r   	__class__r   r   r     s   
zOrderedEnqueuer.__init__c                    s    fdd}|S )r   c                    s(   t d t| d t fd}t| |S NT)ZinitializerZinitargs)r   init_pool_generatorr   _DATA_POOLSaddr   poolr   r   r   pool_fn  s   

z3OrderedEnqueuer._get_executor_init.<locals>.pool_fnr   r   r   r   r   r   r   r     s   	z"OrderedEnqueuer._get_executor_initc                 C   s(   	 t d | jjdks| j rdS q)zWait for the queue to be empty.T皙?r   N)timesleepr   r   r   r   r   r   r   r   _wait_queue  s
   
zOrderedEnqueuer._wait_queuec                 C   s   t tt| j}|   	 | jrt| t| t	<}|D ]}| j
 r0 W d   dS | jj|t| j|fdd q |   | j
 rR	 W d   dS W d   n1 s\w   Y  | j  |   qr   TNblock)r%   r   ry   r   r   r   randomr   r   r   r   r   r   putapply_asyncr   r   r   r   )r   r   executorr   r   r   r   r     s,   



zOrderedEnqueuer._runc              
   c   s    |   rCz| jjddd }|   r| j  |dur |V  W n tjy+   Y n ty< } z|   |d}~ww |   sdS dS )Creates a generator to extract data from the queue.

    Skip the data if it is `None`.

    Yields:
        The next element in the queue, i.e. a tuple
        `(inputs, targets)` or
        `(inputs, targets, sample_weights)`.
    T   r   r   N)r   r   r   	task_doneEmptyrb   r   )r   inputsrr   r   r   r   r     s"   

zOrderedEnqueuer.get)FF)
rN   rO   rP   r   r   r   r   r   r   __classcell__r   r   r   r   r     s    r   c                 C   sV   | a t }d|j|_|durtj||j  |dur)|j	|jddd dS dS )a  Initializer function for pool workers.

  Args:
    gens: State which should be made available to worker processes.
    random_seed: An optional value with which to seed child processes.
    id_queue: A multiprocessing Queue of worker ids. This is used to indicate
      that a worker process was created by Keras and can be terminated using
      the cleanup_all_keras_forkpools utility.
  zKeras_worker_{}NTr   r   )
r   r   current_processrc   namer+   r   seedidentr   )Zgensrandom_seedZid_queueZworker_procr   r   r   r     s   r   c                 C   s   t t|  S )aK  Gets the next value from the generator `uid`.

  To allow multiple generators to be used at the same time, we use `uid` to
  get a specific one. A single generator would cause the validation to
  overwrite the training generator.

  Args:
      uid: int, generator identifier

  Returns:
      The next value of generator `uid`.
  )r   r   )r   r   r   r   next_sample  s   r  c                       s>   e Zd ZdZ		d fdd	Zdd Zdd	 Zd
d Z  ZS )GeneratorEnqueuera  Builds a queue out of a data generator.

  The provided generator can be finite in which case the class will throw
  a `StopIteration` exception.

  Args:
      generator: a generator function which yields data
      use_multiprocessing: use multiprocessing if True, otherwise threading
      random_seed: Initial seed for workers,
          will be incremented by one for each worker.
  FNc                    r   r}   )r   r	  r   r  )r   	generatorr   r  r   r   r   r   4  s   
zGeneratorEnqueuer.__init__c                    s    fdd}|S )zGets the Pool initializer for multiprocessing.

    Args:
      workers: Number of works.

    Returns:
        A Function to initialize the pool
    c                    s*   t dt|  jt fd}t| |S r   )r   r   r  r   r   r   r   r   r   r   r   C  s   
z5GeneratorEnqueuer._get_executor_init.<locals>.pool_fnr   r   r   r   r   r   :  s   	z$GeneratorEnqueuer._get_executor_initc                 C   sh   |    t| t}	 | j r	 W d   dS | jj|t	| j
fdd q1 s-w   Y  dS r   )r   r   r   r   r   r   r   r   r   r  r   )r   r   r   r   r   r   K  s   
zGeneratorEnqueuer._runc              
   c   s    z#|   r"| jjdd }| j  |dur|V  |   sW dS W dS  tyd   g }| j dkrE|| jjdd | j dks4|D ]}|  qGdd |D }|D ]	}|dur`|V  qWY dS  ty } z| 	  dt
|v rytd|d}~ww )	r   Tr   Nr   c                 S   s   g | ]
}|  r| qS r   )Z
successfulr   )r   futurer   r   r   
<listcomp>o  s    z)GeneratorEnqueuer.get.<locals>.<listcomp>zgenerator already executingzyYour generator is NOT thread-safe. Keras requires a thread-safe generator when `use_multiprocessing=False, workers > 1`. )r   r   r   r   StopIterationqsizeappendwaitrb   r   r$   r=   )r   r  Z	last_onesr   rr   r   r   r   r   V  s<   


zGeneratorEnqueuer.get)FN)	rN   rO   rP   r   r   r   r   r   r  r   r   r   r   r	  '  s    r	  )NN)r2   r3   )FNNrJ   r3   Fr3   Nr}   )rv   r{   )r3   r{   )Dr   abcr   
contextlibr   r   rx   r   Zmultiprocessing.dummyr?   r   r   rD   sysr6   r   r   r.   r_   weakrefr8   numpyr+   Ztensorflow.python.frameworkr   Zsix.moves.urllib.requestr   Ztensorflow.python.keras.utilsr   Z+tensorflow.python.keras.utils.generic_utilsr   Z&tensorflow.python.keras.utils.io_utilsr   version_infor#   urllib.requestr1   rI   rs   r[   rz   r   r\   r^   r   r   r-   r   r   r   WeakSetr   r   r(   Z_WORKER_IDSr   RLockr   r   r   r   r   r   r   r   r   r  r	  r   r   r   r   <module>   s   %

3
 


"	N 
Y