"""simple docstring"""







import argparse
import os
import re

import numpy as np
import PIL
import torch
from timm import create_model
from torch.optim.lr_scheduler import OneCycleLR
from torch.utils.data import DataLoader, Dataset
from torchvision.transforms import Compose, RandomResizedCrop, Resize, ToTensor

from accelerate import Accelerator



def 			lowercase__(       __SCREAMING_SNAKE_CASE							:     List[Any]      ):
     lowercase_	:				List[str]													=	fname.split(os.path.sep      )[-1]
     return re.search(R'^(.*)_\d+\.jpg$'     ,			__SCREAMING_SNAKE_CASE      ).groups()[0]







class        UpperCamelCase		(			lowercase_  ):
   def __init__(			self     ,__UpperCamelCase     ,__UpperCamelCase=None     ,__UpperCamelCase=None			)	->      Dict:


        '''simple docstring'''


        lowercase_	:				str													=	file_names
        lowercase_	:				Union[str, Any]													=	image_transform
        lowercase_	:				int													=	label_to_id
   def __len__(			self			)	->      Optional[Any]:


        '''simple docstring'''


        return len(self.file_names			)







   def __getitem__(			self     ,__UpperCamelCase			)	->      Tuple:


        '''simple docstring'''


        lowercase_	:				Any													=	self.file_names[idx]
        lowercase_	:				List[Any]													=	PIL.Image.open(__UpperCamelCase			)
        lowercase_	:				Union[str, Any]													=	raw_image.convert('RGB'			)
        if self.image_transform is not None:
             lowercase_	:				Optional[int]													=	self.image_transform(__UpperCamelCase			)
        lowercase_	:				Dict													=	extract_label(__UpperCamelCase			)
        if self.label_to_id is not None:
             lowercase_	:				str													=	self.label_to_id[label]
        return {"image": image, "label": label}






def 			lowercase__(       __SCREAMING_SNAKE_CASE							:     List[str]     ,			__SCREAMING_SNAKE_CASE							:     Union[str, Any]      ):
     # Initialize accelerator
     if args.with_tracking:
          lowercase_	:				str													=	Accelerator(
              cpu=args.cpu     ,			mixed_precision=args.mixed_precision     ,			log_with='all'     ,			project_dir=args.project_dir      )
     else:
          lowercase_	:				Optional[int]													=	Accelerator(cpu=args.cpu     ,			mixed_precision=args.mixed_precision      )

     # Sample hyper-parameters for learning rate, batch size, seed and a few other HPs
     lowercase_	:				List[str]													=	config['lr']
     lowercase_	:				List[Any]													=	int(config['num_epochs']      )
     lowercase_	:				Any													=	int(config['seed']      )
     lowercase_	:				Optional[Any]													=	int(config['batch_size']      )
     lowercase_	:				Optional[Any]													=	config['image_size']
     if not isinstance(__SCREAMING_SNAKE_CASE     ,			(list, tuple)      ):
          lowercase_	:				Dict													=	(image_size, image_size)

     # Parse out whether we are saving every epoch or after a certain number of batches
     if hasattr(args.checkpointing_steps     ,			'isdigit'      ):
          if args.checkpointing_steps == "epoch":
               lowercase_	:				int													=	args.checkpointing_steps
          elif args.checkpointing_steps.isdigit():
               lowercase_	:				Optional[Any]													=	int(args.checkpointing_steps      )
          else:
               raise ValueError(
                   F'''Argument `checkpointing_steps` must be either a number or `epoch`. `{args.checkpointing_steps}` passed.'''      )
     else:
          lowercase_	:				Any													=	None

     # We need to initialize the trackers we use, and also store our configuration
     if args.with_tracking:
          lowercase_	:				Optional[Any]													=	os.path.split(__SCREAMING_SNAKE_CASE      )[-1].split('.'      )[0]
          accelerator.init_trackers(__SCREAMING_SNAKE_CASE     ,			__SCREAMING_SNAKE_CASE      )

     # Grab all the image filenames
     lowercase_	:				List[str]													=	[os.path.join(args.data_dir     ,			__SCREAMING_SNAKE_CASE      ) for fname in os.listdir(args.data_dir      ) if fname.endswith('.jpg'      )]

     # Build the label correspondences
     lowercase_	:				Optional[int]													=	[extract_label(__SCREAMING_SNAKE_CASE      ) for fname in file_names]
     lowercase_	:				List[Any]													=	list(set(__SCREAMING_SNAKE_CASE      )      )
     id_to_label.sort()
     lowercase_	:				int													=	{lbl: i for i, lbl in enumerate(__SCREAMING_SNAKE_CASE      )}

     # Set the seed before splitting the data.
     np.random.seed(__SCREAMING_SNAKE_CASE      )
     torch.manual_seed(__SCREAMING_SNAKE_CASE      )
     torch.cuda.manual_seed_all(__SCREAMING_SNAKE_CASE      )

     # Split our filenames between train and validation
     lowercase_	:				Dict													=	np.random.permutation(len(__SCREAMING_SNAKE_CASE      )      )
     lowercase_	:				Optional[Any]													=	int(0.8 * len(__SCREAMING_SNAKE_CASE      )      )
     lowercase_	:				Dict													=	random_perm[:cut]
     lowercase_	:				int													=	random_perm[cut:]

     # For training we use a simple RandomResizedCrop
     lowercase_	:				Any													=	Compose([RandomResizedCrop(__SCREAMING_SNAKE_CASE     ,			scale=(0.5, 1.0)      ), ToTensor()]      )
     lowercase_	:				Union[str, Any]													=	PetsDataset(
         [file_names[i] for i in train_split]     ,			image_transform=__SCREAMING_SNAKE_CASE     ,			label_to_id=__SCREAMING_SNAKE_CASE      )

     # For evaluation, we use a deterministic Resize
     lowercase_	:				Optional[int]													=	Compose([Resize(__SCREAMING_SNAKE_CASE      ), ToTensor()]      )
     lowercase_	:				Any													=	PetsDataset([file_names[i] for i in eval_split]     ,			image_transform=__SCREAMING_SNAKE_CASE     ,			label_to_id=__SCREAMING_SNAKE_CASE      )

     # Instantiate dataloaders.
     lowercase_	:				Any													=	DataLoader(__SCREAMING_SNAKE_CASE     ,			shuffle=__SCREAMING_SNAKE_CASE     ,			batch_size=__SCREAMING_SNAKE_CASE     ,			num_workers=4      )
     lowercase_	:				str													=	DataLoader(__SCREAMING_SNAKE_CASE     ,			shuffle=__SCREAMING_SNAKE_CASE     ,			batch_size=__SCREAMING_SNAKE_CASE     ,			num_workers=4      )

     # Instantiate the model (we build the model here so that the seed also control new weights initialization)
     lowercase_	:				Union[str, Any]													=	create_model('resnet50d'     ,			pretrained=__SCREAMING_SNAKE_CASE     ,			num_classes=len(__SCREAMING_SNAKE_CASE      )      )

     # We could avoid this line since the accelerator is set with `device_placement=True` (default value).
     # Note that if you are placing tensors on devices manually, this line absolutely needs to be before the optimizer
     # creation otherwise training will not work on TPU (`accelerate` will kindly throw an error to make us aware of that).
     lowercase_	:				int													=	model.to(accelerator.device      )

     # Freezing the base model
     for param in model.parameters():
          lowercase_	:				Any													=	False
     for param in model.get_classifier().parameters():
          lowercase_	:				Union[str, Any]													=	True

     # We normalize the batches of images to be a bit faster.
     lowercase_	:				Dict													=	torch.tensor(model.default_cfg['mean']      )[None, :, None, None].to(accelerator.device      )
     lowercase_	:				List[Any]													=	torch.tensor(model.default_cfg['std']      )[None, :, None, None].to(accelerator.device      )

     # Instantiate optimizer
     lowercase_	:				int													=	torch.optim.Adam(params=model.parameters()     ,			lr=lr / 25      )

     # Instantiate learning rate scheduler
     lowercase_	:				Union[str, Any]													=	OneCycleLR(optimizer=__SCREAMING_SNAKE_CASE     ,			max_lr=__SCREAMING_SNAKE_CASE     ,			epochs=__SCREAMING_SNAKE_CASE     ,			steps_per_epoch=len(__SCREAMING_SNAKE_CASE      )      )

     # Prepare everything
     # There is no specific order to remember, we just need to unpack the objects in the same order we gave them to the
     # prepare method.
     lowercase_							,  lowercase_							,  lowercase_							,  lowercase_							,  lowercase_	:				Union[str, Any]													=	accelerator.prepare(
         __SCREAMING_SNAKE_CASE     ,			__SCREAMING_SNAKE_CASE     ,			__SCREAMING_SNAKE_CASE     ,			__SCREAMING_SNAKE_CASE     ,			__SCREAMING_SNAKE_CASE      )
     # We need to keep track of how many total steps we have iterated over
     lowercase_	:				Optional[int]													=	0
     # We also need to keep track of the starting epoch so files are named properly
     lowercase_	:				Tuple													=	0

     # Potentially load in the weights and states from a previous save
     if args.resume_from_checkpoint:
          if args.resume_from_checkpoint is not None or args.resume_from_checkpoint != "":
               accelerator.print(F'''Resumed from checkpoint: {args.resume_from_checkpoint}'''      )
               accelerator.load_state(args.resume_from_checkpoint      )
               lowercase_	:				Tuple													=	os.path.basename(args.resume_from_checkpoint      )
          else:
               # Get the most recent checkpoint
               lowercase_	:				List[str]													=	[f.name for f in os.scandir(os.getcwd()      ) if f.is_dir()]
               dirs.sort(key=os.path.getctime      )
               lowercase_	:				List[str]													=	dirs[-1]  # Sorts folders by date modified, most recent checkpoint is the last
          # Extract `epoch_{i}` or `step_{i}`
          lowercase_	:				Union[str, Any]													=	os.path.splitext(__SCREAMING_SNAKE_CASE      )[0]

          if "epoch" in training_difference:
               lowercase_	:				Tuple													=	int(training_difference.replace('epoch_'     ,			''      )      ) + 1
               lowercase_	:				Union[str, Any]													=	None
          else:
               lowercase_	:				List[str]													=	int(training_difference.replace('step_'     ,			''      )      )
               lowercase_	:				str													=	resume_step // len(__SCREAMING_SNAKE_CASE      )
               resume_step -= starting_epoch * len(__SCREAMING_SNAKE_CASE      )

    # Now we train the model
     for epoch in range(__SCREAMING_SNAKE_CASE     ,			__SCREAMING_SNAKE_CASE      ):
          model.train()
          if args.with_tracking:
               lowercase_	:				List[Any]													=	0
          if args.resume_from_checkpoint and epoch == starting_epoch and resume_step is not None:
               # We need to skip steps until we reach the resumed step
               lowercase_	:				Optional[Any]													=	accelerator.skip_first_batches(__SCREAMING_SNAKE_CASE     ,			__SCREAMING_SNAKE_CASE      )
               overall_step += resume_step
          else:
               # After the first iteration though, we need to go back to the original dataloader
               lowercase_	:				int													=	train_dataloader
          for batch in active_dataloader:
               # We could avoid this line since we set the accelerator with `device_placement=True`.
               lowercase_	:				int													=	{k: v.to(accelerator.device      ) for k, v in batch.items()}
               lowercase_	:				str													=	(batch['image'] - mean) / std
               lowercase_	:				Tuple													=	model(__SCREAMING_SNAKE_CASE      )
               lowercase_	:				int													=	torch.nn.functional.cross_entropy(__SCREAMING_SNAKE_CASE     ,			batch['label']      )
               # We keep track of the loss at each epoch
               if args.with_tracking:
                    total_loss += loss.detach().float()
               accelerator.backward(__SCREAMING_SNAKE_CASE      )
               optimizer.step()
               lr_scheduler.step()
               optimizer.zero_grad()
               overall_step += 1
               if isinstance(__SCREAMING_SNAKE_CASE     ,			__SCREAMING_SNAKE_CASE      ):
                    lowercase_	:				Any													=	F'''step_{overall_step}'''
                    if overall_step % checkpointing_steps == 0:
                         if args.output_dir is not None:
                              lowercase_	:				Union[str, Any]													=	os.path.join(args.output_dir     ,			__SCREAMING_SNAKE_CASE      )
                         accelerator.save_state(__SCREAMING_SNAKE_CASE      )
          model.eval()
          lowercase_	:				Optional[int]													=	0
          lowercase_	:				Union[str, Any]													=	0
          for step, batch in enumerate(__SCREAMING_SNAKE_CASE      ):
               # We could avoid this line since we set the accelerator with `device_placement=True`.
               lowercase_	:				List[Any]													=	{k: v.to(accelerator.device      ) for k, v in batch.items()}
               lowercase_	:				Optional[Any]													=	(batch['image'] - mean) / std
               with torch.no_grad():
                    lowercase_	:				int													=	model(__SCREAMING_SNAKE_CASE      )
               lowercase_	:				Dict													=	outputs.argmax(dim=-1      )
               lowercase_							,  lowercase_	:				Any													=	accelerator.gather_for_metrics((predictions, batch['label'])      )
               lowercase_	:				Tuple													=	predictions == references
               num_elems += accurate_preds.shape[0]
               accurate += accurate_preds.long().sum()

          lowercase_	:				str													=	accurate.item() / num_elems
          # Use accelerator.print to print only on the main process.
          accelerator.print(F'''epoch {epoch}: {1_00 * eval_metric:.2f}'''      )
          if args.with_tracking:
               accelerator.log(
                   {
                       'accuracy': 1_00 * eval_metric,
                       'train_loss': total_loss.item() / len(__SCREAMING_SNAKE_CASE      ),
                       'epoch': epoch,
                   }     ,			step=__SCREAMING_SNAKE_CASE     ,			)
          if checkpointing_steps == "epoch":
               lowercase_	:				int													=	F'''epoch_{epoch}'''
               if args.output_dir is not None:
                    lowercase_	:				int													=	os.path.join(args.output_dir     ,			__SCREAMING_SNAKE_CASE      )
               accelerator.save_state(__SCREAMING_SNAKE_CASE      )

     if args.with_tracking:
          accelerator.end_training()



def 			lowercase__(       ):
     lowercase_	:				Optional[int]													=	argparse.ArgumentParser(description='Simple example of training script.'      )
     parser.add_argument('--data_dir'     ,			required=__SCREAMING_SNAKE_CASE     ,			help='The data folder on disk.'      )
     parser.add_argument('--fp16'     ,			action='store_true'     ,			help='If passed, will use FP16 training.'      )
     parser.add_argument(
         '--mixed_precision'     ,			type=__SCREAMING_SNAKE_CASE     ,			default=__SCREAMING_SNAKE_CASE     ,			choices=['no', 'fp16', 'bf16', 'fp8']     ,			help='Whether to use mixed precision. Choose'
         'between fp16 and bf16 (bfloat16). Bf16 requires PyTorch >= 1.10.'
         'and an Nvidia Ampere GPU.'     ,			)
     parser.add_argument('--cpu'     ,			action='store_true'     ,			help='If passed, will train on the CPU.'      )
     parser.add_argument(
         '--checkpointing_steps'     ,			type=__SCREAMING_SNAKE_CASE     ,			default=__SCREAMING_SNAKE_CASE     ,			help='Whether the various states should be saved at the end of every n steps, or \'epoch\' for each epoch.'     ,			)
     parser.add_argument(
         '--output_dir'     ,			type=__SCREAMING_SNAKE_CASE     ,			default='.'     ,			help='Optional save directory where all checkpoint folders will be stored. Default is the current working directory.'     ,			)
     parser.add_argument(
         '--resume_from_checkpoint'     ,			type=__SCREAMING_SNAKE_CASE     ,			default=__SCREAMING_SNAKE_CASE     ,			help='If the training should continue from a checkpoint folder.'     ,			)
     parser.add_argument(
         '--with_tracking'     ,			action='store_true'     ,			help='Whether to load in all available experiment trackers from the environment and use them for logging.'     ,			)
     parser.add_argument(
         '--project_dir'     ,			type=__SCREAMING_SNAKE_CASE     ,			default='logs'     ,			help='Location on where to store experiment tracking logs` and relevent project information'     ,			)
     lowercase_	:				Optional[int]													=	parser.parse_args()
     lowercase_	:				int													=	{'lr': 3E-2, 'num_epochs': 3, 'seed': 42, 'batch_size': 64, 'image_size': 2_24}
     training_function(__SCREAMING_SNAKE_CASE     ,			__SCREAMING_SNAKE_CASE      )


if __name__ == "__main__":
       main()


"""simple docstring"""







import argparse
import struct
import unittest







class        UpperCamelCase		:
   def __init__(			self     ,__UpperCamelCase			)	->      None:


        '''simple docstring'''


        lowercase_	:				str													=	data

        # Initialize hash values
        lowercase_	:				Optional[int]													=	[
            0X6_A_0_9_E_6_6_7,
            0XB_B_6_7_A_E_8_5,
            0X3_C_6_E_F_3_7_2,
            0XA_5_4_F_F_5_3_A,
            0X5_1_0_E_5_2_7_F,
            0X9_B_0_5_6_8_8_C,
            0X1_F_8_3_D_9_A_B,
            0X5_B_E_0_C_D_1_9,
        ]

        # Initialize round constants
        lowercase_	:				Tuple													=	[
            0X4_2_8_A_2_F_9_8,
            0X7_1_3_7_4_4_9_1,
            0XB_5_C_0_F_B_C_F,
            0XE_9_B_5_D_B_A_5,
            0X3_9_5_6_C_2_5_B,
            0X5_9_F_1_1_1_F_1,
            0X9_2_3_F_8_2_A_4,
            0XA_B_1_C_5_E_D_5,
            0XD_8_0_7_A_A_9_8,
            0X1_2_8_3_5_B_0_1,
            0X2_4_3_1_8_5_B_E,
            0X5_5_0_C_7_D_C_3,
            0X7_2_B_E_5_D_7_4,
            0X8_0_D_E_B_1_F_E,
            0X9_B_D_C_0_6_A_7,
            0XC_1_9_B_F_1_7_4,
            0XE_4_9_B_6_9_C_1,
            0XE_F_B_E_4_7_8_6,
            0X0_F_C_1_9_D_C_6,
            0X2_4_0_C_A_1_C_C,
            0X2_D_E_9_2_C_6_F,
            0X4_A_7_4_8_4_A_A,
            0X5_C_B_0_A_9_D_C,
            0X7_6_F_9_8_8_D_A,
            0X9_8_3_E_5_1_5_2,
            0XA_8_3_1_C_6_6_D,
            0XB_0_0_3_2_7_C_8,
            0XB_F_5_9_7_F_C_7,
            0XC_6_E_0_0_B_F_3,
            0XD_5_A_7_9_1_4_7,
            0X0_6_C_A_6_3_5_1,
            0X1_4_2_9_2_9_6_7,
            0X2_7_B_7_0_A_8_5,
            0X2_E_1_B_2_1_3_8,
            0X4_D_2_C_6_D_F_C,
            0X5_3_3_8_0_D_1_3,
            0X6_5_0_A_7_3_5_4,
            0X7_6_6_A_0_A_B_B,
            0X8_1_C_2_C_9_2_E,
            0X9_2_7_2_2_C_8_5,
            0XA_2_B_F_E_8_A_1,
            0XA_8_1_A_6_6_4_B,
            0XC_2_4_B_8_B_7_0,
            0XC_7_6_C_5_1_A_3,
            0XD_1_9_2_E_8_1_9,
            0XD_6_9_9_0_6_2_4,
            0XF_4_0_E_3_5_8_5,
            0X1_0_6_A_A_0_7_0,
            0X1_9_A_4_C_1_1_6,
            0X1_E_3_7_6_C_0_8,
            0X2_7_4_8_7_7_4_C,
            0X3_4_B_0_B_C_B_5,
            0X3_9_1_C_0_C_B_3,
            0X4_E_D_8_A_A_4_A,
            0X5_B_9_C_C_A_4_F,
            0X6_8_2_E_6_F_F_3,
            0X7_4_8_F_8_2_E_E,
            0X7_8_A_5_6_3_6_F,
            0X8_4_C_8_7_8_1_4,
            0X8_C_C_7_0_2_0_8,
            0X9_0_B_E_F_F_F_A,
            0XA_4_5_0_6_C_E_B,
            0XB_E_F_9_A_3_F_7,
            0XC_6_7_1_7_8_F_2,
        ]

        lowercase_	:				Tuple													=	self.preprocessing(self.data			)
        self.final_hash()
   @staticmethod
   def 			_UpperCAmelCase   (			__UpperCamelCase			)	->      bytes:


        '''simple docstring'''


        lowercase_	:				str													=	B'\x80' + (B'\x00' * (63 - (len(__UpperCamelCase			) + 8) % 64))
        lowercase_	:				str													=	struct.pack('>Q'     ,(len(__UpperCamelCase			) * 8)			)
        return data + padding + big_endian_integer
   def 			_UpperCAmelCase   (			self			)	->      None:


        '''simple docstring'''


        lowercase_	:				Optional[Any]													=	[
            self.preprocessed_data[x : x + 64]
            for x in range(0     ,len(self.preprocessed_data			)     ,64			)
        ]

        for block in self.blocks:
             # Convert the given block into a list of 4 byte integers
             lowercase_	:				Any													=	list(struct.unpack('>16L'     ,__UpperCamelCase			)			)
             # add 48 0-ed integers
             words += [0] * 48

             lowercase_							,  lowercase_							,  lowercase_							,  lowercase_							,  lowercase_							,  lowercase_							,  lowercase_							,  lowercase_	:				Optional[int]													=	self.hashes

             for index in range(0     ,64			):
                  if index > 15:
                       # modify the zero-ed indexes at the end of the array
                       lowercase_	:				str													=	(
                           self.ror(words[index - 15]     ,7			)
                           ^ self.ror(words[index - 15]     ,18			)
                           ^ (words[index - 15] >> 3)
                       )
                       lowercase_	:				int													=	(
                           self.ror(words[index - 2]     ,17			)
                           ^ self.ror(words[index - 2]     ,19			)
                           ^ (words[index - 2] >> 10)
                       )

                       lowercase_	:				Optional[Any]													=	(
                           words[index - 16] + sa + words[index - 7] + sa
                       ) % 0X1_0_0_0_0_0_0_0_0

                  # Compression
                  lowercase_	:				Tuple													=	self.ror(__UpperCamelCase     ,6			) ^ self.ror(__UpperCamelCase     ,11			) ^ self.ror(__UpperCamelCase     ,25			)
                  lowercase_	:				Union[str, Any]													=	(e & f) ^ ((~e & 0XF_F_F_F_F_F_F_F) & g)
                  lowercase_	:				str													=	(
                      h + sa + ch + self.round_constants[index] + words[index]
                  ) % 0X1_0_0_0_0_0_0_0_0
                  lowercase_	:				Optional[int]													=	self.ror(__UpperCamelCase     ,2			) ^ self.ror(__UpperCamelCase     ,13			) ^ self.ror(__UpperCamelCase     ,22			)
                  lowercase_	:				Optional[Any]													=	(a & b) ^ (a & c) ^ (b & c)
                  lowercase_	:				Any													=	(sa + maj) % 0X1_0_0_0_0_0_0_0_0

                  lowercase_							,  lowercase_							,  lowercase_							,  lowercase_							,  lowercase_							,  lowercase_							,  lowercase_							,  lowercase_	:				Tuple													=	(
                      g,
                      f,
                      e,
                      ((d + tempa) % 0X1_0_0_0_0_0_0_0_0),
                      c,
                      b,
                      a,
                      ((tempa + tempa) % 0X1_0_0_0_0_0_0_0_0),
                  )

             lowercase_	:				str													=	[a, b, c, d, e, f, g, h]

             # Modify final values
             lowercase_	:				Dict													=	[
                 ((element + mutated_hash_values[index]) % 0X1_0_0_0_0_0_0_0_0)
                 for index, element in enumerate(self.hashes			)
             ]

        lowercase_	:				Any													=	''.join([hex(__UpperCamelCase			)[2:].zfill(8			) for value in self.hashes]			)







   def 			_UpperCAmelCase   (			self     ,__UpperCamelCase     ,__UpperCamelCase			)	->      int:


        '''simple docstring'''


        return 0XF_F_F_F_F_F_F_F & (value << (32 - rotations)) | (value >> rotations)







class        UpperCamelCase		(			unittest.TestCase  ):
   def 			_UpperCAmelCase   (			self			)	->      None:


        '''simple docstring'''


        import hashlib

        lowercase_	:				Union[str, Any]													=	bytes('Test String'     ,'utf-8'			)
        self.assertEqual(SHAaaa(__UpperCamelCase			).hash     ,hashlib.shaaaa(__UpperCamelCase			).hexdigest()			)






def 			lowercase__(       ):
     import doctest

     doctest.testmod()

     lowercase_	:				Tuple													=	argparse.ArgumentParser()
     parser.add_argument(
         '-s'     ,			'--string'     ,			dest='input_string'     ,			default='Hello World!! Welcome to Cryptography'     ,			help='Hash the string'     ,			)
     parser.add_argument(
         '-f'     ,			'--file'     ,			dest='input_file'     ,			help='Hash contents of a file'      )

     lowercase_	:				Any													=	parser.parse_args()

     lowercase_	:				int													=	args.input_string

     # hash input should be a bytestring
     if args.input_file:
          with open(args.input_file     ,			'rb'      ) as f:
               lowercase_	:				str													=	f.read()
     else:
          lowercase_	:				Optional[int]													=	bytes(__SCREAMING_SNAKE_CASE     ,			'utf-8'      )

     print(SHAaaa(__SCREAMING_SNAKE_CASE      ).hash      )


if __name__ == "__main__":
       main()

