from datetime import datetime from dateutil.relativedelta import relativedelta import pandas as pd import os import re import boto3 from garcon_contrib.aws.utils import garcon_s3 from dotenv import load_dotenv load_dotenv() def _get_list_of_files_and_directories(s3_path): """Get the list of files and dirs in given S3 directory (prefix). Args: s3_path (str): S3 directory (prefix) to list the files and dirs. Returns: files_list (list): List of the files in directories in given S3 path. """ s3 = boto3.client('s3') bucket, bucket_path = garcon_s3.extract_bucket_path(s3_path) paginator = s3.get_paginator('list_objects') operation_parameters = {'Bucket': bucket, 'Prefix': bucket_path} page_iterator = paginator.paginate(**operation_parameters) files_and_directories = [] for page in page_iterator: for key in page.get('Contents', []): files_and_directories.append( {'fileName': key['Key'].replace('ftp/youtube/',''), 'lastModified': key[ 'LastModified'].strftime("%m/%d/%Y, %H:%M:%S")}) return files_and_directories def retrieve_and_export_filenames_to_csv(s3_path, export_csv_full_path): """Get the list of files and dirs in given S3 directory (prefix) and export to csv. Args: s3_path (str): S3 directory (prefix) to list the files and dirs. export_csv_full_path (str): full path of the csv file Returns: files_list (list): List of the files in directories in given S3 path. """ try: file_list = _get_list_of_files_and_directories(s3_path) except Exception as e: print('Extraction failed with the error message: {}'.format(e)) files_df = pd.DataFrame(file_list) files_df.to_csv(export_csv_full_path, index=False) return {'success': True, 'exported_path': export_csv_full_path} def _identify_report_frequency(filename): if '_D_' in filename: freq = 'daily' elif '_W_' in filename: freq = 'weekly' else: freq = 'monthly' return freq def _increment_date(date, freq): if freq == 'daily': incremented_date = date + relativedelta(days=1) elif freq == 'weekly': incremented_date = date + relativedelta(days=7) else: incremented_date = date + relativedelta(months=1) return incremented_date def _extract_entries_matching_pattern(pattern, df, colname): matched_entries = df[df[colname].str.contains(pattern, na=False)] return matched_entries def _add_start_date_col(df, colname): df['start_date'] = \ df['colname'].apply(lambda x: datetime.strptime(re.findall( r'\d{8}', x)[0], '%Y%m%d')) return df def _determine_start_and_end_dates(extracted_df): min_start_date = extracted_df.start_date.min() max_start_date = extracted_df.start_date.max() result = (min_start_date, max_start_date) return result def _extract_availability_dict(extracted_df, min_start_date, max_start_date, freq): avail_list = [] date_ = min_start_date while date_ <= max_start_date: date_str = datetime.strftime(date_, '%Y%m%d') date_str_count = extracted_df['fileName'].str.contains(date_str).sum() if date_str_count > 0: append_ = date_str + ': ' + 'DELIVERED' else: append_ = date_str + ': ' + 'NOT DELIVERED' avail_list.append(append_) date_ = _increment_date(date_, freq) result = '\n'.join(avail_list) return result def extract_avail_info(filename_pattern, youtube_df): freq = _identify_report_frequency(filename_pattern) extracted_df = _extract_entries_matching_pattern(filename_pattern, youtube_df) extracted_df_with_cols = _add_start_date_col(extracted_df) range_start, range_end = _determine_start_and_end_dates(extracted_df) avail_dict = _extract_availability_dict(extracted_df_with_cols, range_start, range_end, freq) result = (range_start.strftime('%Y-%m-%d'), range_end.strftime( '%Y-%m-%d'), avail_dict) return result if __name__ == '__main__': s3_drop_path = f's3://prod-orcd-ftp/ftp/youtube' txt_export = 'youtube_ftp_filenames.csv' reports = 'list_of_newly_added_yt_reports.csv' if os.path.exists(txt_export): youtube_files_df = pd.read_csv(txt_export, sep=',', header=0) else: result = retrieve_and_export_filenames_to_csv(s3_drop_path, txt_export) if result['success']: youtube_files_df = pd.read_csv(txt_export, sep=',', header=0) files_to_be_checked = pd.read_csv(reports, sep=',', header=0) files_to_be_checked['fileName_regexp'] = \ files_to_be_checked.Name.replace( to_replace='\d{8}', regex=True, value='\d{8}') for index, row in files_to_be_checked.iterrows(): if row['Status / Availability'] != 'Deprecated': pattern = '^' + row['fileName_regexp'] start_range, end_range, avail_status = \ extract_avail_info(pattern, youtube_files_df) files_to_be_checked.at[index, 'start_range'] = start_range files_to_be_checked.at[index, 'end_range'] = end_range files_to_be_checked.at[index, 'avail_status'] = avail_status files_to_be_checked.to_excel('newly_added_reports_with_avail.xlsx', index=False)