






import itertools
import random
import unittest

import numpy as np

from transformers import EncodecFeatureExtractor
from transformers.testing_utils import require_torch
from transformers.utils.import_utils import is_torch_available

from ...test_sequence_feature_extraction_common import SequenceFeatureExtractionTestMixin


if is_torch_available():
				import torch


__A          = random.Random()




def    __A    (   _lowercase    ,	_lowercase=1.0    ,	_lowercase=None    ,	_lowercase=None       ):

					'''simple docstring'''







					if rng is None:
										_A									=       global_rng

					_A									=       []
					for batch_idx in range(shape[0]       ):
										values.append([]       )
										for _ in range(shape[1]       ):
															values[-1].append(rng.random() * scale       )

					return values





@require_torch
class   SCREAMING_SNAKE_CASE (       unittest.TestCase    ):





							"""simple docstring"""

							def __init__(     self:      int						,   __A:      Any						,   __A:      List[str]=7						,   __A:      str=4_00						,   __A:      Optional[Any]=20_00						,   __A:      List[Any]=1						,   __A:      List[str]=0.0						,   __A:      Optional[Any]=2_40_00						,   __A:      Dict=True						,   )			-> Tuple:
												_A									=       parent
												_A									=       batch_size
												_A									=       min_seq_length
												_A									=       max_seq_length
												_A									=       (self.max_seq_length - self.min_seq_length) // (self.batch_size - 1)
												_A									=       feature_size
												_A									=       padding_value
												_A									=       sampling_rate
												_A									=       return_attention_mask

							def 					__A       (     self:      List[Any]      )			-> str:
												return {
												    "feature_size": self.feature_size,
												    "padding_value": self.padding_value,
												    "sampling_rate": self.sampling_rate,
												    "return_attention_mask": self.return_attention_mask,
												}



							def 					__A       (     self:      Optional[int]						,   __A:      Dict=False						,   __A:      List[Any]=False      )			-> Tuple:
												def _flatten(__A:      Optional[int]      ):
																	return list(itertools.chain(*__A      )      )

												if equal_length:
																	_A									=       floats_list((self.batch_size, self.max_seq_length)      )
												else:
																	# make sure that inputs increase in size
																	_A									=       [
																	    _flatten(floats_list((x, self.feature_size)      )      )
																	    for x in range(self.min_seq_length						,   self.max_seq_length						,   self.seq_length_diff      )
																	]

												if numpify:
																	_A									=       [np.asarray(__A      ) for x in audio_inputs]

												return audio_inputs





@require_torch
class   SCREAMING_SNAKE_CASE (       snake_case     ,		unittest.TestCase    ):





							"""simple docstring"""

							A_       =    EncodecFeatureExtractor

							def 					__A       (     self:      Any      )			-> Tuple:
												_A									=       EnCodecFeatureExtractionTester(self      )

							def 					__A       (     self:      Union[str, Any]      )			-> List[Any]:
												# Tests that all call wrap to encode_plus and batch_encode_plus
												_A									=       self.feature_extraction_class(**self.feat_extract_tester.prepare_feat_extract_dict()      )
												# create three inputs of length 800, 1000, and 1200
												_A									=       [floats_list((1, x)      )[0] for x in range(8_00						,   14_00						,   2_00      )]
												_A									=       [np.asarray(__A      ) for audio_input in audio_inputs]

												# Test not batched input
												_A									=       feat_extract(audio_inputs[0]						,   return_tensors='''np'''      ).input_values
												_A									=       feat_extract(np_audio_inputs[0]						,   return_tensors='''np'''      ).input_values
												self.assertTrue(np.allclose(__A						,   __A						,   atol=1e-3      )      )

												# Test batched
												_A									=       feat_extract(__A						,   padding=__A						,   return_tensors='''np'''      ).input_values
												_A									=       feat_extract(__A						,   padding=__A						,   return_tensors='''np'''      ).input_values
												for enc_seq_a, enc_seq_a in zip(__A						,   __A      ):
																	self.assertTrue(np.allclose(__A						,   __A						,   atol=1e-3      )      )

							def 					__A       (     self:      Optional[int]      )			-> Optional[Any]:
												_A									=       self.feature_extraction_class(**self.feat_extract_tester.prepare_feat_extract_dict()      )
												_A									=       np.random.rand(1_00      ).astype(np.floataa      )
												_A									=       np_audio_inputs.tolist()

												for inputs in [py_audio_inputs, np_audio_inputs]:
																	_A									=       feature_extractor.pad([{'''input_values''': inputs}]						,   return_tensors='''np'''      )
																	self.assertTrue(np_processed.input_values.dtype == np.floataa      )
																	_A									=       feature_extractor.pad([{'''input_values''': inputs}]						,   return_tensors='''pt'''      )
																	self.assertTrue(pt_processed.input_values.dtype == torch.floataa      )

							def 					__A       (     self:      Optional[int]						,   __A:      Optional[Any]      )			-> Any:
												from datasets import load_dataset

												_A									=       load_dataset('''hf-internal-testing/librispeech_asr_dummy'''						,   '''clean'''						,   split='''validation'''      )
												# automatic decoding with librispeech
												_A									=       ds.sort('''id'''      ).select(range(__A      )      )[:num_samples]['''audio''']

												return [x["array"] for x in audio_samples]

							def 					__A       (     self:      List[str]      )			-> List[str]:
												# fmt: off
												_A									=       torch.tensor(
												    [2.38_04e-03, 2.07_52e-03, 1.98_36e-03, 2.10_57e-03, 1.61_74e-03,
												     3.05_18e-04, 9.15_53e-05, 3.35_69e-04, 9.76_56e-04, 1.83_11e-03,
												     2.01_42e-03, 2.10_57e-03, 1.73_95e-03, 4.57_76e-04, -3.96_73e-04,
												     4.57_76e-04, 1.00_71e-03, 9.15_53e-05, 4.88_28e-04, 1.15_97e-03,
												     7.32_42e-04, 9.46_04e-04, 1.80_05e-03, 1.83_11e-03, 8.85_01e-04,
												     4.27_25e-04, 4.88_28e-04, 7.32_42e-04, 1.09_86e-03, 2.10_57e-03]      )
												# fmt: on
												_A									=       self._load_datasamples(1      )
												_A									=       EncodecFeatureExtractor()
												_A									=       feature_extractor(__A						,   return_tensors='''pt'''      ).input_values
												self.assertEquals(input_values.shape						,   (1, 1, 9_36_80)      )
												self.assertTrue(torch.allclose(input_values[0, 0, :30]						,   __A						,   atol=1e-6      )      )

							def 					__A       (     self:      Optional[Any]      )			-> Optional[int]:
												# fmt: off
												_A									=       torch.tensor(
												    [2.38_04e-03, 2.07_52e-03, 1.98_36e-03, 2.10_57e-03, 1.61_74e-03,
												     3.05_18e-04, 9.15_53e-05, 3.35_69e-04, 9.76_56e-04, 1.83_11e-03,
												     2.01_42e-03, 2.10_57e-03, 1.73_95e-03, 4.57_76e-04, -3.96_73e-04,
												     4.57_76e-04, 1.00_71e-03, 9.15_53e-05, 4.88_28e-04, 1.15_97e-03,
												     7.32_42e-04, 9.46_04e-04, 1.80_05e-03, 1.83_11e-03, 8.85_01e-04,
												     4.27_25e-04, 4.88_28e-04, 7.32_42e-04, 1.09_86e-03, 2.10_57e-03]      )
												# fmt: on
												_A									=       self._load_datasamples(1      )
												_A									=       [np.tile(input_audio[0][None]						,   reps=(2, 1)      )]
												input_audio[0][1] *= 0.5
												_A									=       EncodecFeatureExtractor(feature_size=2      )
												_A									=       feature_extractor(__A						,   return_tensors='''pt'''      ).input_values
												self.assertEquals(input_values.shape						,   (1, 2, 9_36_80)      )
												self.assertTrue(torch.allclose(input_values[0, 0, :30]						,   __A						,   atol=1e-6      )      )
												self.assertTrue(torch.allclose(input_values[0, 1, :30]						,   EXPECTED_INPUT_VALUES * 0.5						,   atol=1e-6      )      )



							def 					__A       (     self:      Any      )			-> int:
												_A									=       self._load_datasamples(2      )
												# would be easier if the stride was like
												_A									=       EncodecFeatureExtractor(feature_size=1						,   chunk_length_s=1						,   overlap=0.01      )

												# pad and trunc raise an error ?
												with self.assertRaisesRegex(
												    __A						,   '''^Both padding and truncation were set. Make sure you only set one.$'''						,   ):
																	_A									=       feature_extractor(
																	    __A						,   padding='''max_length'''						,   truncation=__A						,   return_tensors='''pt'''      ).input_values

												# truncate to chunk
												_A									=       feature_extractor(__A						,   truncation=__A						,   return_tensors='''pt'''      ).input_values
												self.assertEquals(truncated_outputs.shape						,   (2, 1, 7_15_20)      )  # 2 chunks

												# force truncate to max_length
												_A									=       feature_extractor(
												    __A						,   truncation=__A						,   max_length=4_80_00						,   return_tensors='''pt'''      ).input_values
												self.assertEquals(truncated_outputs.shape						,   (2, 1, 4_80_00)      )

												# pad to chunk
												_A									=       feature_extractor(__A						,   padding=__A						,   return_tensors='''pt'''      ).input_values
												self.assertEquals(padded_outputs.shape						,   (2, 1, 9_52_80)      )

												# pad to chunk
												_A									=       feature_extractor(__A						,   return_tensors='''pt'''      ).input_values
												self.assertEquals(truncated_outputs.shape						,   (2, 1, 9_52_80)      )

												# force pad to max length
												_A									=       feature_extractor(
												    __A						,   padding='''max_length'''						,   max_length=10_00_00						,   return_tensors='''pt'''      ).input_values
												self.assertEquals(truncated_outputs.shape						,   (2, 1, 10_00_00)      )

												# force no pad
												with self.assertRaisesRegex(
												    __A						,   '''^Unable to create tensor, you should probably activate padding with \'padding=True\' to have batched tensors with the same length.$'''						,   ):
																	_A									=       feature_extractor(__A						,   padding=__A						,   return_tensors='''pt'''      ).input_values

												_A									=       feature_extractor(input_audio[0]						,   padding=__A						,   return_tensors='''pt'''      ).input_values
												self.assertEquals(truncated_outputs.shape						,   (1, 1, 9_36_80)      )

												# no pad if no chunk_length_s
												_A									=       None
												with self.assertRaisesRegex(
												    __A						,   '''^Unable to create tensor, you should probably activate padding with \'padding=True\' to have batched tensors with the same length.$'''						,   ):
																	_A									=       feature_extractor(__A						,   padding=__A						,   return_tensors='''pt'''      ).input_values

												_A									=       feature_extractor(input_audio[0]						,   padding=__A						,   return_tensors='''pt'''      ).input_values
												self.assertEquals(truncated_outputs.shape						,   (1, 1, 9_36_80)      )

												# no pad if no overlap
												_A									=       2
												_A									=       None
												with self.assertRaisesRegex(
												    __A						,   '''^Unable to create tensor, you should probably activate padding with \'padding=True\' to have batched tensors with the same length.$'''						,   ):
																	_A									=       feature_extractor(__A						,   padding=__A						,   return_tensors='''pt'''      ).input_values

												_A									=       feature_extractor(input_audio[0]						,   padding=__A						,   return_tensors='''pt'''      ).input_values
												self.assertEquals(truncated_outputs.shape						,   (1, 1, 9_36_80)      )










import argparse
import os

import evaluate
import torch
from datasets import load_dataset
from torch.optim import AdamW
from torch.utils.data import DataLoader
from transformers import AutoModelForSequenceClassification, AutoTokenizer, get_linear_schedule_with_warmup, set_seed

from accelerate import Accelerator, DistributedType


########################################################################
# This is a fully working simple example to use Accelerate,
# specifically showcasing the checkpointing capability,
# and builds off the `nlp_example.py` script.
#
# This example trains a Bert base model on GLUE MRPC
# in any of the following settings (with the same script):
#   - single CPU or single GPU
#   - multi GPUS (using PyTorch distributed mode)
#   - (multi) TPUs
#   - fp16 (mixed-precision) or fp32 (normal precision)
#
# To help focus on the differences in the code, building `DataLoaders`
# was refactored into its own function.
# New additions from the base script can be found quickly by
# looking for the # New Code # tags
#
# To run it in each of these various modes, follow the instructions
# in the readme for examples:
# https://github.com/huggingface/accelerate/tree/main/examples
#
########################################################################

UpperCAmelCase__  :	Union[str, Any]     =16
UpperCAmelCase__  :	List[Any]     =32





def    _lowercase    (  _UpperCAmelCase	,					_UpperCAmelCase = 16 )  ->     Dict:
				lowerCamelCase		       =AutoTokenizer.from_pretrained("""bert-base-cased""" )
				lowerCamelCase		       =load_dataset("""glue"""	,					"""mrpc""" )

				def tokenize_function(_UpperCAmelCase ):
								# max_length=None => use the model max length (it's actually the default)
								lowerCamelCase		       =tokenizer(examples["""sentence1"""]	,					examples["""sentence2"""]	,					truncation=_UpperCAmelCase	,					max_length=_UpperCAmelCase )
								return outputs

				# Apply the method we just defined to all the examples in all the splits of the dataset
				# starting with the main process first:
				with accelerator.main_process_first():
								lowerCamelCase		       =datasets.map(
								    _UpperCAmelCase	,					batched=_UpperCAmelCase	,					remove_columns=["""idx""", """sentence1""", """sentence2"""]	,					)

				# We also rename the 'label' column to 'labels' which is the expected name for labels by the models of the
				# transformers library
				lowerCamelCase		       =tokenized_datasets.rename_column("""label"""	,					"""labels""" )

				def collate_fn(_UpperCAmelCase ):
								# On TPU it's best to pad everything to the same length or training will be very slow.
								lowerCamelCase		       =1_28 if accelerator.distributed_type == DistributedType.TPU else None
								# When using mixed precision we want round multiples of 8/16
								if accelerator.mixed_precision == "fp8":
												lowerCamelCase		       =16
								elif accelerator.mixed_precision != "no":
												lowerCamelCase		       =8
								else:
												lowerCamelCase		       =None

								return tokenizer.pad(
								    _UpperCAmelCase	,					padding="""longest"""	,					max_length=_UpperCAmelCase	,					pad_to_multiple_of=_UpperCAmelCase	,					return_tensors="""pt"""	,					)

				# Instantiate dataloaders.
				lowerCamelCase		       =DataLoader(
				    tokenized_datasets["""train"""]	,					shuffle=_UpperCAmelCase	,					collate_fn=_UpperCAmelCase	,					batch_size=_UpperCAmelCase )
				lowerCamelCase		       =DataLoader(
				    tokenized_datasets["""validation"""]	,					shuffle=_UpperCAmelCase	,					collate_fn=_UpperCAmelCase	,					batch_size=_UpperCAmelCase )

				return train_dataloader, eval_dataloader


# For testing only
if os.environ.get('''TESTING_MOCKED_DATALOADERS''', None) == "1":
							from accelerate.test_utils.training import mocked_dataloaders

							UpperCAmelCase__  :	Union[str, Any]     =mocked_dataloaders  # noqa: F811





def    _lowercase    (  _UpperCAmelCase	,					_UpperCAmelCase )  ->     List[Any]:
				# For testing only
				if os.environ.get("""TESTING_MOCKED_DATALOADERS"""	,					_UpperCAmelCase ) == "1":
								lowerCamelCase		       =2
				# Initialize accelerator
				lowerCamelCase		       =Accelerator(cpu=args.cpu	,					mixed_precision=args.mixed_precision )
				# Sample hyper-parameters for learning rate, batch size, seed and a few other HPs
				lowerCamelCase		       =config["""lr"""]
				lowerCamelCase		       =int(config["""num_epochs"""] )
				lowerCamelCase		       =int(config["""seed"""] )
				lowerCamelCase		       =int(config["""batch_size"""] )

				# New Code #
				# 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":
												lowerCamelCase		       =args.checkpointing_steps
								elif args.checkpointing_steps.isdigit():
												lowerCamelCase		       =int(args.checkpointing_steps )
								else:
												raise ValueError(
												    F"""Argument `checkpointing_steps` must be either a number or `epoch`. `{args.checkpointing_steps}` passed.""" )
				else:
								lowerCamelCase		       =None

				set_seed(_UpperCAmelCase )

				lowerCamelCase       ,     lowerCamelCase		       =get_dataloaders(_UpperCAmelCase	,					_UpperCAmelCase )
				lowerCamelCase		       =evaluate.load("""glue"""	,					"""mrpc""" )

				# If the batch size is too big we use gradient accumulation
				lowerCamelCase		       =1
				if batch_size > MAX_GPU_BATCH_SIZE and accelerator.distributed_type != DistributedType.TPU:
								lowerCamelCase		       =batch_size // MAX_GPU_BATCH_SIZE
								lowerCamelCase		       =MAX_GPU_BATCH_SIZE

				# Instantiate the model (we build the model here so that the seed also control new weights initialization)
				lowerCamelCase		       =AutoModelForSequenceClassification.from_pretrained("""bert-base-cased"""	,					return_dict=_UpperCAmelCase )

				# 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).
				lowerCamelCase		       =model.to(accelerator.device )

				# Instantiate optimizer
				lowerCamelCase		       =AdamW(params=model.parameters()	,					lr=_UpperCAmelCase )

				# Instantiate scheduler
				lowerCamelCase		       =get_linear_schedule_with_warmup(
				    optimizer=_UpperCAmelCase	,					num_warmup_steps=1_00	,					num_training_steps=(len(_UpperCAmelCase ) * num_epochs) // gradient_accumulation_steps	,					)

				# 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.
				lowerCamelCase       ,     lowerCamelCase       ,     lowerCamelCase       ,     lowerCamelCase       ,     lowerCamelCase		       =accelerator.prepare(
				    _UpperCAmelCase	,					_UpperCAmelCase	,					_UpperCAmelCase	,					_UpperCAmelCase	,					_UpperCAmelCase )

				# New Code #
				# We need to keep track of how many total steps we have iterated over
				lowerCamelCase		       =0
				# We also need to keep track of the stating epoch so files are named properly
				lowerCamelCase		       =0

				# We need to load the checkpoint back in before training here with `load_state`
				# The total number of epochs is adjusted based on where the state is being loaded from,
				# as we assume continuation of the same training script
				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 )
												lowerCamelCase		       =os.path.basename(args.resume_from_checkpoint )
								else:
												# Get the most recent checkpoint
												lowerCamelCase		       =[f.name for f in os.scandir(os.getcwd() ) if f.is_dir()]
												dirs.sort(key=os.path.getctime )
												lowerCamelCase		       =dirs[-1]  # Sorts folders by date modified, most recent checkpoint is the last
								# Extract `epoch_{i}` or `step_{i}`
								lowerCamelCase		       =os.path.splitext(_UpperCAmelCase )[0]

								if "epoch" in training_difference:
												lowerCamelCase		       =int(training_difference.replace("""epoch_"""	,					"""""" ) ) + 1
												lowerCamelCase		       =None
								else:
												lowerCamelCase		       =int(training_difference.replace("""step_"""	,					"""""" ) )
												lowerCamelCase		       =resume_step // len(_UpperCAmelCase )
												resume_step -= starting_epoch * len(_UpperCAmelCase )

    # Now we train the model
				for epoch in range(_UpperCAmelCase	,					_UpperCAmelCase ):
								model.train()
								# New Code #
								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
												lowerCamelCase		       =accelerator.skip_first_batches(_UpperCAmelCase	,					_UpperCAmelCase )
												overall_step += resume_step
								else:
												# After the first iteration though, we need to go back to the original dataloader
												lowerCamelCase		       =train_dataloader
								for step, batch in enumerate(_UpperCAmelCase ):
												# We could avoid this line since we set the accelerator with `device_placement=True`.
												batch.to(accelerator.device )
												lowerCamelCase		       =model(**_UpperCAmelCase )
												lowerCamelCase		       =outputs.loss
												lowerCamelCase		       =loss / gradient_accumulation_steps
												accelerator.backward(_UpperCAmelCase )
												if step % gradient_accumulation_steps == 0:
																optimizer.step()
																lr_scheduler.step()
																optimizer.zero_grad()
												# New Code #
												overall_step += 1

												# New Code #
												# We save the model, optimizer, lr_scheduler, and seed states by calling `save_state`
												# These are saved to folders named `step_{overall_step}`
												# Will contain files: "pytorch_model.bin", "optimizer.bin", "scheduler.bin", and "random_states.pkl"
												# If mixed precision was used, will also save a "scalar.bin" file
												if isinstance(_UpperCAmelCase	,					_UpperCAmelCase ):
																lowerCamelCase		       =F"""step_{overall_step}"""
																if overall_step % checkpointing_steps == 0:
																				if args.output_dir is not None:
																								lowerCamelCase		       =os.path.join(args.output_dir	,					_UpperCAmelCase )
																				accelerator.save_state(_UpperCAmelCase )

								model.eval()
								for step, batch in enumerate(_UpperCAmelCase ):
												# We could avoid this line since we set the accelerator with `device_placement=True` (the default).
												batch.to(accelerator.device )
												with torch.no_grad():
																lowerCamelCase		       =model(**_UpperCAmelCase )
												lowerCamelCase		       =outputs.logits.argmax(dim=-1 )
												lowerCamelCase       ,     lowerCamelCase		       =accelerator.gather_for_metrics((predictions, batch["""labels"""]) )
												metric.add_batch(
												    predictions=_UpperCAmelCase	,					references=_UpperCAmelCase	,					)

								lowerCamelCase		       =metric.compute()
								# Use accelerator.print to print only on the main process.
								accelerator.print(F"""epoch {epoch}:"""	,					_UpperCAmelCase )

								# New Code #
								# We save the model, optimizer, lr_scheduler, and seed states by calling `save_state`
								# These are saved to folders named `epoch_{epoch}`
								# Will contain files: "pytorch_model.bin", "optimizer.bin", "scheduler.bin", and "random_states.pkl"
								# If mixed precision was used, will also save a "scalar.bin" file
								if checkpointing_steps == "epoch":
												lowerCamelCase		       =F"""epoch_{epoch}"""
												if args.output_dir is not None:
																lowerCamelCase		       =os.path.join(args.output_dir	,					_UpperCAmelCase )
												accelerator.save_state(_UpperCAmelCase )





def    _lowercase    (  )  ->     str:
				lowerCamelCase		       =argparse.ArgumentParser(description="""Simple example of training script.""" )
				parser.add_argument(
				    """--mixed_precision"""	,					type=_UpperCAmelCase	,					default=_UpperCAmelCase	,					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=_UpperCAmelCase	,					default=_UpperCAmelCase	,					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=_UpperCAmelCase	,					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=_UpperCAmelCase	,					default=_UpperCAmelCase	,					help="""If the training should continue from a checkpoint folder."""	,					)
				lowerCamelCase		       =parser.parse_args()
				lowerCamelCase		       ={"""lr""": 2e-5, """num_epochs""": 3, """seed""": 42, """batch_size""": 16}
				training_function(_UpperCAmelCase	,					_UpperCAmelCase )


if __name__ == "__main__":
							main()





