
    'wff                     :    d dl m Z   G d d      Z G d de      Zy)    datetimec                   z    e Zd ZdZdZed        Zd Zd Zd Z	d Z
d Zd	 Zd
 Zd Zd Zed        Zed        Zy)InventoryReporta  
    A utility class for fetching and processing inventory reports from GCS.

    The 'InventoryReport' class provides logic to support logic to fetch
    inventory reports, and process their content to obtain a final snapshot
    of objects in the latest inventory reports.

    High-Level Functionality:
    ------------------------
    1. Fetching Inventory Reports:
       - The class offers methods to fetch inventory report configurations and
         metadata from GCS.
       - It validates the inventory report information provided by the user.
       - Inventory report configurations include options for parsing CSV format
         and specifying the bucket and destination path.

    2. Parsing and Processing Inventory Report Content:
       - The class processes the raw content of inventory reports to extract
         object details such as name, size, etc.
       - It supports listing objects using a snapshot option or filtering
         based on a user-defined prefix.
       - The class handles CSV parsing, removes header (if specified), and
         fetches required object metadata.

    3. Constructing the Final Snapshot:
       - If the user wishes to use the snapshot to do listing directly, the
         snapshot will contain the relevant object details and subdirectory
         prefixes, filtered by the prefix.

       - If the user wishes to use the snapshot as a starting point for async
         listing, the snapshot will only contain a list of object names,
         filtered by the prefix.

    Note:
    -----
    - The class should only be internally used in the 'GCSFileSystem' as an
      optional configuration during listing.

    Example Usage:
    --------------
    # Should already be instanted in 'core.py'
    gcs_file_system = GCSFileSystem(...)

    # User defines inventory report information
    inventory_report_info = {
        "use_snapshot_listing": True,
        "location": "us-east1",
        "id": "inventory_report_id"
    }

    # User defines a prefix for filtering objects
    prefix = "prefix/"

    # Fetch the snapshot based on inventory reports
    items, prefixes = await InventoryReport.fetch_snapshot(
    gcs_file_system, inventory_report_info, prefix)
    z)https://storageinsights.googleapis.com/v1c                   K   | j                  |       |j                  d      }|j                  d      }|j                  d      }| j                  |||       d{   }| j                  ||      }| j	                  ||       d{   }	| j                  |	      }
|j                  }| j                  ||
|	       d{   }| j                  |||||
      }| j                  |||      }|S 7 7 l7 4w)a  
        Main entry point of the 'InventoryReport' class.
        Fetches the latest snapshot of objects based on inventory report configuration.

        Parameters:
            gcs_file_system (GCSFileSystem): An instance of the 'GCSFileSystem'
            class (see 'core.py').
            inventory_report_info (dict): A client-configured dictionary
            containing inventory report information.
            prefix (str): Listing prefix specified by the client.

        Returns:
            tuple: A tuple containing two lists: the 'items' list representing
            object details for the snapshot, and the 'prefixes' list containing
            subdirectory prefixes.

            Note: when 'use_snapshot_listing' in 'inventory_report_info' is set
            to False, the 'prefixes' list will be empty, and the 'items' list
            will contain only the object names.
        use_snapshot_listinglocationid)gcs_file_systemr	   r
   N)raw_inventory_report_configr   )r   inventory_report_config"unsorted_inventory_report_metadata)r   inventory_report_metadatabucket)r   inventory_report_contentr   r   r   )objectsprefixr   )
_validate_inventory_report_infoget"_fetch_raw_inventory_report_config"_parse_raw_inventory_report_config _fetch_inventory_report_metadata_sort_inventory_report_metadatar   "_download_inventory_report_content_parse_inventory_report_content_construct_final_snapshot)clsr   inventory_report_infor   r   inventory_report_locationinventory_report_idr   r   r   r   r   r   r   snapshots                  j/home/panchajanya/Development/work/volatility3/venv/lib/python3.12/site-packages/gcsfs/inventory_report.pyfetch_snapshotzInventoryReport.fetch_snapshotB   sc    . 	++,AB  5889OP$9$=$=j$I!377= -0,R,R+." -S -
 '
# #&"H"H(C!5 #I #
 473W3W+$; 4X 4
 .
* %($G$G/Q %H %
!
 )//),)O)O+&? *P *
 $
  55+%=$;!5 6 
 00FAU 1 

 ]'
.
$
s6   AC=C7-C=C99C=C;1C=9C=;C=c                 ^    d| vrt        d      d| vrt        d      d| vrt        d      y)a  
        Validates the inventory report information dictionary that user
        passes in.

        Parameters:
            inventory_report_info (dict): A dictionary containing the inventory
            report information with the following keys:
                - "use_snapshot_listing" (bool): A flag indicating whether
                  to use snapshot listing in the inventory report.
                - "location" (str): The location of the inventory report in GCS.
                - "id" (str): The ID of the inventory report in GCS.

        Raises:
            ValueError: If any required key (use_snapshot_listing, location, id)
            is missing from the inventory_report_info dictionary.
        r   z'Use snapshot listing is not configured.r	   z,Inventory report location is not configured.r
   z&Inventory report id is not configured.N)
ValueError)r   s    r#   r   z/InventoryReport._validate_inventory_report_info   sH    " ")>>FGG22KLL,,EFF -    c                    K   | j                   }d}|j                  t        j                  |||      }	 | j	                  d|d       d{   }|S 7 # t
        $ r}t        d| d      d}~ww xY ww)a  
        Fetches the raw inventory report configuration from GCS based on the
        specified location and ID.

        Parameters:
            gcs_file_system (GCSFileSystem): An instance of the 'GCSFileSystem'
            class (see 'core.py').
            location (str): The location of the inventory report in GCS.
            id (str): The ID of the inventory report in GCS.

        Returns:
            dict: A dictionary containing the raw inventory report
            configuration retrieved from GCS.

        Raises:
            Exception: If there is an error while fetching the inventory
            report configuration.
        z,{}/projects/{}/locations/{}/reportConfigs/{}GETT)json_outNz9Error encountered when fetching inventory report config: .)projectformatr   BASE_URL_call	Exceptionr&   )r   r	   r
   r,   urlr   es          r#   r   z2InventoryReport._fetch_raw_inventory_report_config   s     & "))<jj117HbI	0?0E0EsT 1F 1 +' /.+  	KA3aP 	s:   1A4A AA A4A 	A1A,,A11A4c           	         | j                  d      }t        j                  |j                  d            }t        j                  |j                  d            }| j                  d      }|j                  d      }| j                  d      }|j                  d      }|j                  d      }	|j                  d	      }
t        j                         }||k  s||kD  rt        d
| d| d| d      |
j                  d      }|r	 |
j                  d       t        |||	|
|      }|S # t
        $ r t        d      w xY w)a  
        Parses the raw inventory report configuration and validates its properties.

        Parameters:
            raw_inventory_report_config (dict): A dictionary containing the raw
            inventory report configuration retrieved from GCS.
            use_snapshot_listing (bool): A flag indicating whether to use snapshot
            listing in the inventory report.

        Returns:
            InventoryReportConfig: An instance of the InventoryReportConfig
            class representing the parsed inventory report configuration.

        Raises:
            ValueError: If the current date is outside the start and
            end range specified in the inventory report config.
            ValueError: If the "name" field is not present in the metadata
            fields of the report config.
            ValueError: If "size" field is not present in the metadata
            fields and use_snapshot_listing is True.
        frequencyOptions	startDateendDateobjectMetadataReportOptionsstorageDestinationOptions
csvOptionsr   destinationPathmetadataFieldszCurrent date z& is outside the range                 z and z* specified by the inventory report config.namesizezIf you want to use the snapshot for listing, the object size                         metadata has to be included in the inventory report.csv_optionsr   destination_pathmetadata_fieldsobj_name_idx)r   r   _convert_obj_to_dater   nowr&   indexInventoryReportConfig)r   r   frequency_options
start_dateend_dateobject_metadata_report_optionsstorage_destination_optionsr?   r   r@   rA   todayrB   r   s                 r#   r   z2InventoryReport._parse_raw_inventory_report_config   s   2 8;;<NO$99!!+.

 #77!!),
 *E)H)H)*
& 'E&H&H''
#
 255lC,00:6::;LM8<<=MN :!1w 'E(+UW  ',,V4  %%f- #8#-+%#
 '&   N s   D* *D?c                   K   g }|j                   }|j                  }| j                  dd||d       d{   }|j                  |j	                  dg              |j	                  dd      }|U| j                  dd||d|       d{   }|j                  |j	                  dg              |j	                  dd      }|Ut        |      d	k(  rt        d
      |S 7 7 Ww)a  
        Fetches all inventory report metadata from GCS based on the specified
        inventory report config.

        Parameters:
            gcs_file_system (GCSFileSystem): An instance of the 'GCSFileSystem'
            class (see 'core.py').
            inventory_report_config (InventoryReportConfig): An instance of
            the InventoryReportConfig class representing the inventory report
            configuration.

        Returns:
            list: A list containing dictionaries representing the metadata of
            objects from the inventory reports.

        Raises:
            ValueError: If the fetched inventory reports are empty.
        r)   zb/{}/oT)r   r*   NitemsnextPageToken)r   r*   	pageTokenr   zbNo inventory reports to fetch. Check if                 your inventory report is set up correctly.)r   r@   r/   extendr   lenr&   )r   r   r   r   r@   pagenext_page_tokens          r#   r   z0InventoryReport._fetch_inventory_report_metadata  s    , %'! )//2CC %**8V,<t + 
 
 	"(('2)>?((?D9 )(..') /  D &,,TXXgr-BC"hh=O ) ()Q.< 
 )(C
s(   4C$C AC$
C"9C$C$"C$c                      t        | d d      S )a  
        Sorts the inventory report metadata based on the 'timeCreated' field
        in reverse chronological order.

        Parameters:
            unsorted_inventory_report_metadata (list): A list of dictionaries
            representing the metadata of objects from the inventory reports.

        Returns:
            list: A sorted list of dictionaries representing the inventory
            report metadata, sorted in reverse chronological order based
            on 'timeCreated'.
        c                 J    t         j                  | j                  d            S )NtimeCreated)r   _convert_str_to_datetimer   )irs    r#   <lambda>zAInventoryReport._sort_inventory_report_metadata.<locals>.<lambda>i  s    ?CC}% r'   T)keyreverse)sortedr   s    r#   r   z/InventoryReport._sort_inventory_report_metadataY  s     . 
 	
r'   c           	        K   |d   }t         j                  |j                  d            j                         }g }|D ]  }t         j                  |d         j                         }||k(  s/| j	                  dd||j                  d      d       d{   \  }}	|	j                         }
|j                  |
        |S 7 ,w)	ax  
        Downloads the most recent inventory report content from GCS based on
        the inventory report metadata.

        Parameters:
            gcs_file_system (GCSFileSystem): An instance of the 'GCSFileSystem'
            class (see 'core.py').
            inventory_report_metadata (list): A list of dictionaries
            representing the metadata of objects from the inventory reports.
            bucket (str): The name of the GCS bucket containing
            the inventory reports.

        Returns:
            list: A list containing the content of the most recent inventory
            report as strings.
        r   rW   r)   z	b/{}/o/{}r<   media)altN)r   rX   r   dater/   decodeappend)r   r   r   most_recent_inventory_reportmost_recent_dater   metadatainventory_report_date_headerencoded_contentdecoded_contents              r#   r   z2InventoryReport._download_inventory_report_contento  s     ( (A'C$*CC(,,];

$& 	 $&  2 	AH$3$L$L'%df " %(88 2A1F1F;V0D' 2G 2 ,(
 #2"8"8":(//@!	A$ (',s   A*C-(CC-Cc           
      2   |j                   }|j                  dd      }|j                  dd      }|j                  dd      }g }	|D ]M  }
|
j                  |      }|r|dd }|D ].  }t        j	                  ||| |||	      }|	j                  |       0 O |	S )
a  
        Parses the raw inventory report content and extracts object details.

        Parameters:
            gcs_file_system (GCSFileSystem): An instance of the 'GCSFileSystem'
            class (see 'core.py').
            inventory_report_content (list): A list of strings containing the
            raw content of the inventory report.
            inventory_report_config (InventoryReportConfig): An instance of the
            InventoryReportConfig class representing the inventory report
            configuration.
            use_snapshot_listing (bool): A flag indicating whether to use snapshot
            listing in the inventory report.
            bucket (str): The name of the GCS bucket containing the inventory
            reports.

        Returns:
            list: A list of dictionaries representing object details parsed
            from the inventory report content.
        recordSeparator
	delimiter,headerRequiredF   N)inventory_report_liner   r   r   rn   r   )r?   r   splitr   _parse_inventory_report_linerc   )r   r   r   r   r   r?   record_separatorrn   header_requiredr   contentlineslineobjs                 r#   r   z/InventoryReport._parse_inventory_report_content  s    8 .99&??+<dCOOK5	%//*:EB/ 	$GMM"23E ab	  
$%BB*.)=$3,C'! C  s#
$	$* r'   c                 0   |j                   }|j                  }|du rO|j                  t        || j	                         j                  |            D 	ci c]  \  }}	||	
 c}	}|      }
|
S d| j	                         j                  |      |   i}
|
S c c}	}w )a  
        Parses a single line of the inventory report and extracts object details.

        Parameters:
            inventory_report_line (str): A string representing a single line of
            the raw content from the inventory report.
            use_snapshot_listing (bool): A flag indicating whether to use snapshot
            listing in the inventory report.
            gcs_file_system (GCSFileSystem): An instance of the 'GCSFileSystem'
            class (see 'core.py').
            inventory_report_config (InventoryReportConfig): An instance of the
            InventoryReportConfig class representing the inventory report
            configuration.
            delimiter (str): The delimiter used in the inventory report content
            to separate fields.
            bucket (str): The name of the GCS bucket containing the inventory
            reports.

        Returns:
            dict: A dictionary representing object details parsed from the
            inventory report line.
        Tr<   )rB   rA   _process_objectzipstriprs   )rr   r   r   r   rn   r   rB   rA   r[   valuerz   s              r#   rt   z,InventoryReport._parse_inventory_report_line  s    < /;;1AA
  4'!11 '*')>)D)D)F)L)LY)W'"U J C 
 0668>>yI,WXC
s   B
c                    |d}|du r3| D cg c]%  }|j                  d      j                  |      s$|' c}g fS g }t               }| D ]  }|j                  d      }|j                  |      s&|t        |      d }|j	                  d      }|dk(  r|j                  |       \|d| }	|j                  d      |dk(  rdndz   |	z   |	dk(  rdndz   }
|j                  |
        |t        |      fS c c}w )aA  
        Constructs the final snapshot based on the retrieved objects and prefix.

        Parameters:
            objects (list): A list of dictionaries representing object details
            from the inventory report.
            prefix (str): A prefix used to filter objects in the snapshot based
            on their names.
            use_snapshot_listing (bool): A flag indicating whether to use snapshot
            listing in the inventory report.

        Returns:
            tuple: A tuple containing two lists: the 'items' list representing
            object details for the snapshot, and the 'prefixes' list containing
            subdirectory prefixes. If 'use_snapshot_listing' is set to False,
            'prefix' will also be empty, and 'items' will contains the object
            names in the snapshot.
        N Fr<   /)	r   
startswithsetrR   findrc   rstripaddlist)r   r   r   rz   rN   prefixesobj_nameobject_name_no_prefixfirst_delimiter_idxdir
obj_prefixs              r#   r   z)InventoryReport._construct_final_snapshot  s1   & >F  5(#*QCcggfo.H.H.PCQSUUU
 EuH )776?
  **62 )1V(?% '<&@&@&E# '",LL% ,,@-@AMM#&#r\rs4 !BYrC1  Z(;)> d8n$$O Rs
   %C3C3c                 :    | d   }| d   }| d   }t        |||      S )a:  
        Converts a dictionary representing a date object to a datetime object.

        Parameters:
            obj (dict): A dictionary representing a date object with keys "day",
            "month", and "year".

        Returns:
            datetime: A datetime object representing the converted date.
        daymonthyearr   )rz   r   r   r   s       r#   rC   z$InventoryReport._convert_obj_to_dateR  s.     %jG6{eS))r'   c                 L    t        j                  | j                  dd            S )a8  
        Converts an ISO-formatted date string to a datetime object.

        Parameters:
            date_string (str): An ISO-formatted date string with or without
            timezone information (Z).

        Returns:
            datetime: A datetime object representing the converted date and time.
        Zz+00:00)r   fromisoformatreplace)strs    r#   rX   z(InventoryReport._convert_str_to_datetimec  s      %%ckk#x&@AAr'   N)__name__
__module____qualname____doc__r.   classmethodr$   r   r   r   r   r   r   r   rt   r   staticmethodrC   rX    r'   r#   r   r      s    8v ;HL L\G0@N'`>)@
,2(h8t1f@%D * *  B Br'   r   c                       e Zd ZdZd Zy)rF   a  
    Represents the configuration for fetching inventory reports.

    Attributes:
        csv_options (dict): A dictionary containing options for parsing CSV
        format in the inventory reports.
        bucket (str): The name of the GCS bucket from which to fetch the
        inventory reports.
        destination_path (str): The path within the GCS bucket where the
        inventory reports are stored.
        metadata_fields (list): A list of strings representing metadata
        fields to be extracted from the inventory reports.
        obj_name_idx (int): The index of the "name" field in the 'metadata_fields'
        list, used to identify object names.
    c                 J    || _         || _        || _        || _        || _        y )Nr>   )selfr?   r   r@   rA   rB   s         r#   __init__zInventoryReportConfig.__init__  s+     ' 0.(r'   N)r   r   r   r   r   r   r'   r#   rF   rF   r  s     )r'   rF   N)r   r   objectrF   r   r'   r#   <module>r      s#    k	B k	B\)F )r'   