






import argparse
import hashlib  # hashlib is only used inside the Test class
import struct


class       __SCREAMING_SNAKE_CASE   :






						def __init__(		self       ,  _UpperCamelCase				):






												"""simple docstring"""
												lowerCAmelCase__        =  data
												lowerCAmelCase__        =  [0X67452301, 0XEFCDAB89, 0X98BADCFE, 0X10325476, 0XC3D2E1F0]






						@staticmethod
						def  UpperCamelCase__ (		_UpperCamelCase       ,  _UpperCamelCase				):






												"""simple docstring"""
												return ((n << b) | (n >> (32 - b))) & 0XFFFFFFFF






						def  UpperCamelCase__ (		self				):






												"""simple docstring"""
												lowerCAmelCase__        =  B'\x80' + B'\x00' * (63 - (len(self.data				) + 8) % 64)
												lowerCAmelCase__        =  self.data + padding + struct.pack('>Q'       ,  8 * len(self.data				)				)
												return padded_data






						def  UpperCamelCase__ (		self				):






												"""simple docstring"""
												return [
												    self.padded_data[i : i + 64] for i in range(0       ,  len(self.padded_data				)       ,  64				)
												]






						def  UpperCamelCase__ (		self       ,  _UpperCamelCase				):






												"""simple docstring"""
												lowerCAmelCase__        =  list(struct.unpack('>16L'       ,  _UpperCamelCase				)				) + [0] * 64
												for i in range(16       ,  80				):
																		lowerCAmelCase__        =  self.rotate((w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16])       ,  1				)
												return w







						def  UpperCamelCase__ (		self				):






												"""simple docstring"""
												lowerCAmelCase__        =  self.padding()
												lowerCAmelCase__        =  self.split_blocks()
												for block in self.blocks:
																		lowerCAmelCase__        =  self.expand_block(_UpperCamelCase				)
																		lowerCAmelCase__  ,    lowerCAmelCase__  ,    lowerCAmelCase__  ,    lowerCAmelCase__  ,    lowerCAmelCase__        =  self.h
																		for i in range(0       ,  80				):
																								if 0 <= i < 20:
																														lowerCAmelCase__        =  (b & c) | ((~b) & d)
																														lowerCAmelCase__        =  0X5A827999
																								elif 20 <= i < 40:
																														lowerCAmelCase__        =  b ^ c ^ d
																														lowerCAmelCase__        =  0X6ED9EBA1
																								elif 40 <= i < 60:
																														lowerCAmelCase__        =  (b & c) | (b & d) | (c & d)
																														lowerCAmelCase__        =  0X8F1BBCDC
																								elif 60 <= i < 80:
																														lowerCAmelCase__        =  b ^ c ^ d
																														lowerCAmelCase__        =  0XCA62C1D6
																								lowerCAmelCase__  ,    lowerCAmelCase__  ,    lowerCAmelCase__  ,    lowerCAmelCase__  ,    lowerCAmelCase__        =  (
																								    self.rotate(_UpperCamelCase       ,  5				) + f + e + k + expanded_block[i] & 0XFFFFFFFF,
																								    a,
																								    self.rotate(_UpperCamelCase       ,  30				),
																								    c,
																								    d,
																								)
																		lowerCAmelCase__        =  (
																		    self.h[0] + a & 0XFFFFFFFF,
																		    self.h[1] + b & 0XFFFFFFFF,
																		    self.h[2] + c & 0XFFFFFFFF,
																		    self.h[3] + d & 0XFFFFFFFF,
																		    self.h[4] + e & 0XFFFFFFFF,
																		)
												return ("{:08x}" * 5).format(*self.h				)







def 		_UpperCamelCase				(      )					->				Optional[int]:

						"""simple docstring"""



						lowerCAmelCase__        =  B'Test String'
						assert SHAaHash(UpperCamelCase_						).final_hash() == hashlib.shaa(UpperCamelCase_						).hexdigest()  # noqa: S324







def 		_UpperCamelCase				(      )					->				Dict:

						"""simple docstring"""



						lowerCAmelCase__        =  argparse.ArgumentParser(description='Process some strings or files'						)
						parser.add_argument(
						    '--string'      ,    dest='input_string'      ,    default='Hello World!! Welcome to Cryptography'      ,    help='Hash the string'      ,    )
						parser.add_argument('--file'      ,    dest='input_file'      ,    help='Hash contents of a file'						)
						lowerCAmelCase__        =  parser.parse_args()
						lowerCAmelCase__        =  args.input_string
						# In any case hash input should be a bytestring
						if args.input_file:
												with open(args.input_file      ,    'rb'						) as f:
																		lowerCAmelCase__        =  f.read()
						else:
												lowerCAmelCase__        =  bytes(UpperCamelCase_      ,    'utf-8'						)
						print(SHAaHash(UpperCamelCase_						).final_hash()						)


if __name__ == "__main__":
					main()
					import doctest

					doctest.testmod()













from collections.abc import Iterator, MutableMapping
from dataclasses import dataclass
from typing import Generic, TypeVar

__snake_case      :      Optional[Any]             =       TypeVar("""KEY""")
__snake_case      :      str             =       TypeVar("""VAL""")


@dataclass(frozen=__lowercase						,   slots=__lowercase)
class       __SCREAMING_SNAKE_CASE   (				Generic[KEY, VAL]):
						_SCREAMING_SNAKE_CASE		:    KEY
						_SCREAMING_SNAKE_CASE		:    VAL




class       __SCREAMING_SNAKE_CASE   (				_Item):






						def __init__(		self				):






												"""simple docstring"""
												super().__init__(_UpperCamelCase       ,  _UpperCamelCase				)







						def __bool__(		self				):






												"""simple docstring"""
												return False




__snake_case      :      int             =       _DeletedItem()


class       __SCREAMING_SNAKE_CASE   (				MutableMapping[KEY, VAL]):






						def __init__(		self       ,  _UpperCamelCase = 8       ,  _UpperCamelCase = 0.75				):






												"""simple docstring"""
												lowerCAmelCase__        =  initial_block_size
												lowerCAmelCase__        =  [None] * initial_block_size
												assert 0.0 < capacity_factor < 1.0
												lowerCAmelCase__        =  capacity_factor
												lowerCAmelCase__        =  0






						def  UpperCamelCase__ (		self       ,  _UpperCamelCase				):






												"""simple docstring"""
												return hash(_UpperCamelCase				) % len(self._buckets				)






						def  UpperCamelCase__ (		self       ,  _UpperCamelCase				):






												"""simple docstring"""
												return (ind + 1) % len(self._buckets				)






						def  UpperCamelCase__ (		self       ,  _UpperCamelCase       ,  _UpperCamelCase       ,  _UpperCamelCase				):






												"""simple docstring"""
												lowerCAmelCase__        =  self._buckets[ind]
												if not stored:
																		lowerCAmelCase__        =  _Item(_UpperCamelCase       ,  _UpperCamelCase				)
																		self._len += 1
																		return True
												elif stored.key == key:
																		lowerCAmelCase__        =  _Item(_UpperCamelCase       ,  _UpperCamelCase				)
																		return True
												else:
																		return False






						def  UpperCamelCase__ (		self				):






												"""simple docstring"""
												lowerCAmelCase__        =  len(self._buckets				) * self._capacity_factor
												return len(self				) >= int(_UpperCamelCase				)






						def  UpperCamelCase__ (		self				):






												"""simple docstring"""
												if len(self._buckets				) <= self._initial_block_size:
																		return False
												lowerCAmelCase__        =  len(self._buckets				) * self._capacity_factor / 2
												return len(self				) < limit






						def  UpperCamelCase__ (		self       ,  _UpperCamelCase				):






												"""simple docstring"""
												lowerCAmelCase__        =  self._buckets
												lowerCAmelCase__        =  [None] * new_size
												lowerCAmelCase__        =  0
												for item in old_buckets:
																		if item:
																								self._add_item(item.key       ,  item.val				)






						def  UpperCamelCase__ (		self				):






												"""simple docstring"""
												self._resize(len(self._buckets				) * 2				)






						def  UpperCamelCase__ (		self				):






												"""simple docstring"""
												self._resize(len(self._buckets				) // 2				)






						def  UpperCamelCase__ (		self       ,  _UpperCamelCase				):






												"""simple docstring"""
												lowerCAmelCase__        =  self._get_bucket_index(_UpperCamelCase				)
												for _ in range(len(self._buckets				)				):
																		yield ind
																		lowerCAmelCase__        =  self._get_next_ind(_UpperCamelCase				)






						def  UpperCamelCase__ (		self       ,  _UpperCamelCase       ,  _UpperCamelCase				):






												"""simple docstring"""
												for ind in self._iterate_buckets(_UpperCamelCase				):
																		if self._try_set(_UpperCamelCase       ,  _UpperCamelCase       ,  _UpperCamelCase				):
																								break






						def __setitem__(		self       ,  _UpperCamelCase       ,  _UpperCamelCase				):






												"""simple docstring"""
												if self._is_full():
																		self._size_up()

												self._add_item(_UpperCamelCase       ,  _UpperCamelCase				)






						def __delitem__(		self       ,  _UpperCamelCase				):






												"""simple docstring"""
												for ind in self._iterate_buckets(_UpperCamelCase				):
																		lowerCAmelCase__        =  self._buckets[ind]
																		if item is None:
																								raise KeyError(_UpperCamelCase				)
																		if item is _deleted:
																								continue
																		if item.key == key:
																								lowerCAmelCase__        =  _deleted
																								self._len -= 1
																								break
												if self._is_sparse():
																		self._size_down()






						def __getitem__(		self       ,  _UpperCamelCase				):






												"""simple docstring"""
												for ind in self._iterate_buckets(_UpperCamelCase				):
																		lowerCAmelCase__        =  self._buckets[ind]
																		if item is None:
																								break
																		if item is _deleted:
																								continue
																		if item.key == key:
																								return item.val
												raise KeyError(_UpperCamelCase				)






						def __len__(		self				):






												"""simple docstring"""
												return self._len






						def __iter__(		self				):






												"""simple docstring"""
												yield from (item.key for item in self._buckets if item)







						def __repr__(		self				):






												"""simple docstring"""
												lowerCAmelCase__        =  ' ,'.join(
												    F"{item.key}: {item.val}" for item in self._buckets if item				)
												return F"HashMap({val_string})"





