




"""simple docstring"""






import os
import posixpath
import uuid
from dataclasses import dataclass
from typing import TYPE_CHECKING, Iterable, List, Optional, Tuple, Union

import numpy as np
import pyarrow as pa

import datasets
from datasets.arrow_writer import ArrowWriter, ParquetWriter
from datasets.config import MAX_SHARD_SIZE
from datasets.filesystems import (
    is_remote_filesystem,
    rename,
)
from datasets.iterable_dataset import _BaseExamplesIterable
from datasets.utils.py_utils import convert_file_size_to_int


lowercase__			=		datasets.utils.logging.get_logger(__name__)

if TYPE_CHECKING:
			import pyspark






@dataclass
class lowerCAmelCase__      (	datasets.BuilderConfig		):






			'''simple docstring'''



			lowerCamelCase__ =     None







def 	_snake_case     (							lowercase__				,       lowercase__				,       ):
				import pyspark

				def generate_fn():
								_lowerCamelCase	:     List[str]       =       df.select('*'				,       pyspark.sql.functions.spark_partition_id().alias('part_id'						)						)
								for partition_id in partition_order:
												_lowerCamelCase	:     Tuple       =       df_with_partition_id.select('*'						).where(f'''part_id = {partition_id}'''						).drop('part_id'						)
												_lowerCamelCase	:     Optional[int]       =       partition_df.collect()
												_lowerCamelCase	:     int       =       0
												for row in rows:
																yield f'''{partition_id}_{row_id}''', row.asDict()
																row_id += 1

				return generate_fn






class lowerCAmelCase__      (	_BaseExamplesIterable		):






			'''simple docstring'''



			def __init__(    self    , lowercase    , lowercase=None    , ):
							_lowerCamelCase	:     Dict       =       df
							_lowerCamelCase	:     List[str]       =       partition_order or range(self.df.rdd.getNumPartitions()    )
							_lowerCamelCase	:     int       =       _generate_iterable_examples(self.df    , self.partition_order    )
			def __iter__(    self    ):
							yield from self.generate_examples_fn()
			def    A_       (    self    , lowercase    ):
							_lowerCamelCase	:     Dict       =       list(range(self.df.rdd.getNumPartitions()    )    )
							generator.shuffle(lowercase    )
							return SparkExamplesIterable(self.df    , partition_order=lowercase    )
			def    A_       (    self    , lowercase    , lowercase    ):
							_lowerCamelCase	:     Optional[Any]       =       self.split_shard_indices_by_worker(lowercase    , lowercase    )
							return SparkExamplesIterable(self.df    , partition_order=lowercase    )






			@property
			def    A_       (    self    ):
							return len(self.partition_order    )






class lowerCAmelCase__      (	datasets.DatasetBuilder		):






			'''simple docstring'''



			lowerCamelCase__ =     SparkConfig
			def __init__(    self    , lowercase    , lowercase = None    , lowercase = None    , **lowercase    , ):
							import pyspark

							_lowerCamelCase	:     List[Any]       =       pyspark.sql.SparkSession.builder.getOrCreate()
							_lowerCamelCase	:     Optional[int]       =       df
							_lowerCamelCase	:     int       =       working_dir

							super().__init__(
							    cache_dir=lowercase    , config_name=str(self.df.semanticHash()    )    , **lowercase    , )
			def    A_       (    self    ):
							# Returns the path of the created file.
							def create_cache_and_write_probe(lowercase    ):
											# makedirs with exist_ok will recursively create the directory. It will not throw an error if directories
											# already exist.
											os.makedirs(self._cache_dir    , exist_ok=lowercase    )
											_lowerCamelCase	:     str       =       os.path.join(self._cache_dir    , 'fs_test' + uuid.uuida().hex    )
											# Opening the file in append mode will create a new file unless it already exists, in which case it will not
											# change the file contents.
											open(lowercase    , 'a'    )
											return [probe_file]

							if self._spark.conf.get('spark.master'    , ''    ).startswith('local'    ):
											return

							# If the cluster is multi-node, make sure that the user provided a cache_dir and that it is on an NFS
							# accessible to the driver.
							# TODO: Stream batches to the driver using ArrowCollectSerializer instead of throwing an error.
							if self._cache_dir:
											_lowerCamelCase	:     Dict       =       (
											    self._spark.sparkContext.parallelize(range(1    )    , 1    ).mapPartitions(lowercase    ).collect()
											)
											if os.path.isfile(probe[0]    ):
															return

							raise ValueError(
							    'When using Dataset.from_spark on a multi-node cluster, the driver and all workers should be able to access cache_dir'    )
			def    A_       (    self    ):
							return datasets.DatasetInfo(features=self.config.features    )
			def    A_       (    self    , lowercase    ):
							return [datasets.SplitGenerator(name=datasets.Split.TRAIN    )]
			def    A_       (    self    , lowercase    ):
							import pyspark

							def get_arrow_batch_size(lowercase    ):
											for batch in it:
															yield pa.RecordBatch.from_pydict({'batch_bytes': [batch.nbytes]}    )

							_lowerCamelCase	:     str       =       self.df.count()
							_lowerCamelCase	:     Any       =       df_num_rows if df_num_rows <= 100 else 100
							# Approximate the size of each row (in Arrow format) by averaging over a max-100-row sample.
							_lowerCamelCase	:     Any       =       (
							    self.df.limit(lowercase    )
							    .repartition(1    )
							    .mapInArrow(lowercase    , 'batch_bytes: long'    )
							    .agg(pyspark.sql.functions.sum('batch_bytes'    ).alias('sample_bytes'    )    )
							    .collect()[0]
							    .sample_bytes
							    / sample_num_rows
							)
							_lowerCamelCase	:     Dict       =       approx_bytes_per_row * df_num_rows
							if approx_total_size > max_shard_size:
											# Make sure there is at least one row per partition.
											_lowerCamelCase	:     Tuple       =       min(lowercase    , int(approx_total_size / max_shard_size    )    )
											_lowerCamelCase	:     Any       =       self.df.repartition(lowercase    )
			def    A_       (    self    , lowercase    , lowercase    , lowercase    , ):
							import pyspark

							_lowerCamelCase	:     Optional[int]       =       ParquetWriter if file_format == 'parquet' else ArrowWriter
							_lowerCamelCase	:     Tuple       =       os.path.join(self._working_dir    , os.path.basename(lowercase    )    ) if self._working_dir else fpath
							_lowerCamelCase	:     Optional[Any]       =       file_format == 'parquet'

							# Define these so that we don't reference self in write_arrow, which will result in a pickling error due to
							# pickling the SparkContext.
							_lowerCamelCase	:     Any       =       self.config.features
							_lowerCamelCase	:     List[Any]       =       self._writer_batch_size
							_lowerCamelCase	:     Tuple       =       self._fs.storage_options

							def write_arrow(lowercase    ):
											# Within the same SparkContext, no two task attempts will share the same attempt ID.
											_lowerCamelCase	:     int       =       pyspark.TaskContext().taskAttemptId()
											_lowerCamelCase	:     int       =       next(lowercase    , lowercase    )
											if first_batch is None:
															# Some partitions might not receive any data.
															return pa.RecordBatch.from_arrays(
															    [[task_id], [0], [0]]    , names=['task_id', 'num_examples', 'num_bytes']    , )
											_lowerCamelCase	:     Dict       =       0
											_lowerCamelCase	:     Optional[int]       =       writer_class(
											    features=lowercase    , path=working_fpath.replace('SSSSS'    , F'''{shard_id:05d}'''    ).replace('TTTTT'    , F'''{task_id:05d}'''    )    , writer_batch_size=lowercase    , storage_options=lowercase    , embed_local_files=lowercase    , )
											_lowerCamelCase	:     List[Any]       =       pa.Table.from_batches([first_batch]    )
											writer.write_table(lowercase    )
											for batch in it:
															if max_shard_size is not None and writer._num_bytes >= max_shard_size:
																			_lowerCamelCase,					_lowerCamelCase	:     Tuple       =       writer.finalize()
																			writer.close()
																			yield pa.RecordBatch.from_arrays(
																			    [[task_id], [num_examples], [num_bytes]]    , names=['task_id', 'num_examples', 'num_bytes']    , )
																			shard_id += 1
																			_lowerCamelCase	:     Tuple       =       writer_class(
																			    features=writer._features    , path=working_fpath.replace('SSSSS'    , F'''{shard_id:05d}'''    ).replace('TTTTT'    , F'''{task_id:05d}'''    )    , writer_batch_size=lowercase    , storage_options=lowercase    , embed_local_files=lowercase    , )
															_lowerCamelCase	:     Optional[int]       =       pa.Table.from_batches([batch]    )
															writer.write_table(lowercase    )

											if writer._num_bytes > 0:
															_lowerCamelCase,					_lowerCamelCase	:     List[str]       =       writer.finalize()
															writer.close()
															yield pa.RecordBatch.from_arrays(
															    [[task_id], [num_examples], [num_bytes]]    , names=['task_id', 'num_examples', 'num_bytes']    , )

											if working_fpath != fpath:
															for file in os.listdir(os.path.dirname(lowercase    )    ):
																			_lowerCamelCase	:     Optional[int]       =       os.path.join(os.path.dirname(lowercase    )    , os.path.basename(lowercase    )    )
																			shutil.move(lowercase    , lowercase    )

							_lowerCamelCase	:     Tuple       =       (
							    self.df.mapInArrow(lowercase    , 'task_id: long, num_examples: long, num_bytes: long'    )
							    .groupBy('task_id'    )
							    .agg(
							        pyspark.sql.functions.sum('num_examples'    ).alias('total_num_examples'    )    , pyspark.sql.functions.sum('num_bytes'    ).alias('total_num_bytes'    )    , pyspark.sql.functions.count('num_bytes'    ).alias('num_shards'    )    , pyspark.sql.functions.collect_list('num_examples'    ).alias('shard_lengths'    )    , )
							    .collect()
							)
							for row in stats:
											yield row.task_id, (row.total_num_examples, row.total_num_bytes, row.num_shards, row.shard_lengths)
			def    A_       (    self    , lowercase    , lowercase = "arrow"    , lowercase = None    , lowercase = None    , **lowercase    , ):
							self._validate_cache_dir()

							_lowerCamelCase	:     str       =       convert_file_size_to_int(max_shard_size or MAX_SHARD_SIZE    )
							self._repartition_df_if_needed(lowercase    )
							_lowerCamelCase	:     Any       =       not is_remote_filesystem(self._fs    )
							_lowerCamelCase	:     str       =       os.path.join if is_local else posixpath.join

							_lowerCamelCase	:     List[Any]       =       '-TTTTT-SSSSS-of-NNNNN'
							_lowerCamelCase	:     List[Any]       =       F'''{self.name}-{split_generator.name}{SUFFIX}.{file_format}'''
							_lowerCamelCase	:     Any       =       path_join(self._output_dir    , lowercase    )

							_lowerCamelCase	:     List[Any]       =       0
							_lowerCamelCase	:     Dict       =       0
							_lowerCamelCase	:     int       =       0
							_lowerCamelCase	:     Any       =       []
							_lowerCamelCase	:     Optional[int]       =       []

							for task_id, content in self._prepare_split_single(lowercase    , lowercase    , lowercase    ):
											(
											    (
											    _lowerCamelCase
											),					(
											    _lowerCamelCase
											),					(
											    _lowerCamelCase
											),					(
											    _lowerCamelCase
											),					
											)	:     str       =       content
											if num_bytes > 0:
															total_num_examples += num_examples
															total_num_bytes += num_bytes
															total_shards += num_shards
															task_id_and_num_shards.append((task_id, num_shards)    )
															all_shard_lengths.extend(lowercase    )

							_lowerCamelCase	:     Any       =       total_num_examples
							_lowerCamelCase	:     Union[str, Any]       =       total_num_bytes

							# should rename everything at the end
							logger.debug(F'''Renaming {total_shards} shards.'''    )
							if total_shards > 1:
											_lowerCamelCase	:     List[str]       =       all_shard_lengths

											# Define fs outside of _rename_shard so that we don't reference self in the function, which will result in a
											# pickling error due to pickling the SparkContext.
											_lowerCamelCase	:     List[str]       =       self._fs

											# use the -SSSSS-of-NNNNN pattern
											def _rename_shard(
											    lowercase    , lowercase    , lowercase    , ):
															rename(
															    lowercase    , fpath.replace('SSSSS'    , F'''{shard_id:05d}'''    ).replace('TTTTT'    , F'''{task_id:05d}'''    )    , fpath.replace('TTTTT-SSSSS'    , F'''{global_shard_id:05d}'''    ).replace('NNNNN'    , F'''{total_shards:05d}'''    )    , )

											_lowerCamelCase	:     int       =       []
											_lowerCamelCase	:     Tuple       =       0
											for i in range(len(lowercase    )    ):
															_lowerCamelCase,					_lowerCamelCase	:     Dict       =       task_id_and_num_shards[i]
															for shard_id in range(lowercase    ):
																			args.append([task_id, shard_id, global_shard_id]    )
																			global_shard_id += 1
											self._spark.sparkContext.parallelize(lowercase    , len(lowercase    )    ).map(lambda lowercase    : _rename_shard(*lowercase    )    ).collect()
							else:
											# don't use any pattern
											_lowerCamelCase	:     Optional[Any]       =       0
											_lowerCamelCase	:     int       =       task_id_and_num_shards[0][0]
											self._rename(
											    fpath.replace('SSSSS'    , F'''{shard_id:05d}'''    ).replace('TTTTT'    , F'''{task_id:05d}'''    )    , fpath.replace(lowercase    , ''    )    , )






			def    A_       (    self    , lowercase    , ):
							return SparkExamplesIterable(self.df    )





"""simple docstring"""






import unittest

from transformers import MPNetConfig, is_torch_available
from transformers.testing_utils import require_torch, slow, torch_device

from ...test_configuration_common import ConfigTester
from ...test_modeling_common import ModelTesterMixin, ids_tensor, random_attention_mask
from ...test_pipeline_mixin import PipelineTesterMixin


if is_torch_available():
			import torch

			from transformers import (
			    MPNetForMaskedLM,
			    MPNetForMultipleChoice,
			    MPNetForQuestionAnswering,
			    MPNetForSequenceClassification,
			    MPNetForTokenClassification,
			    MPNetModel,
			)






class lowerCAmelCase__      :






			'''simple docstring'''



			def __init__(    self    , lowercase    , lowercase=13    , lowercase=7    , lowercase=True    , lowercase=True    , lowercase=False    , lowercase=True    , lowercase=99    , lowercase=64    , lowercase=5    , lowercase=4    , lowercase=64    , lowercase="gelu"    , lowercase=0.1    , lowercase=0.1    , lowercase=512    , lowercase=16    , lowercase=2    , lowercase=0.02    , lowercase=3    , lowercase=4    , lowercase=None    , ):
							_lowerCamelCase	:     List[str]       =       parent
							_lowerCamelCase	:     List[str]       =       batch_size
							_lowerCamelCase	:     Tuple       =       seq_length
							_lowerCamelCase	:     List[Any]       =       is_training
							_lowerCamelCase	:     int       =       use_input_mask
							_lowerCamelCase	:     Optional[Any]       =       use_token_type_ids
							_lowerCamelCase	:     List[Any]       =       use_labels
							_lowerCamelCase	:     str       =       vocab_size
							_lowerCamelCase	:     Optional[int]       =       hidden_size
							_lowerCamelCase	:     List[str]       =       num_hidden_layers
							_lowerCamelCase	:     Optional[int]       =       num_attention_heads
							_lowerCamelCase	:     List[str]       =       intermediate_size
							_lowerCamelCase	:     int       =       hidden_act
							_lowerCamelCase	:     Optional[int]       =       hidden_dropout_prob
							_lowerCamelCase	:     List[Any]       =       attention_probs_dropout_prob
							_lowerCamelCase	:     List[str]       =       max_position_embeddings
							_lowerCamelCase	:     List[Any]       =       type_vocab_size
							_lowerCamelCase	:     Optional[int]       =       type_sequence_label_size
							_lowerCamelCase	:     Union[str, Any]       =       initializer_range
							_lowerCamelCase	:     Tuple       =       num_labels
							_lowerCamelCase	:     int       =       num_choices
							_lowerCamelCase	:     int       =       scope
			def    A_       (    self    ):
							return MPNetConfig.from_pretrained('microsoft/mpnet-base'    )
			def    A_       (    self    ):
							_lowerCamelCase	:     Tuple       =       ids_tensor([self.batch_size, self.seq_length]    , self.vocab_size    )

							_lowerCamelCase	:     Dict       =       None
							if self.use_input_mask:
											_lowerCamelCase	:     Optional[int]       =       random_attention_mask([self.batch_size, self.seq_length]    )

							_lowerCamelCase	:     int       =       None
							_lowerCamelCase	:     List[str]       =       None
							_lowerCamelCase	:     Any       =       None
							if self.use_labels:
											_lowerCamelCase	:     List[str]       =       ids_tensor([self.batch_size]    , self.type_sequence_label_size    )
											_lowerCamelCase	:     str       =       ids_tensor([self.batch_size, self.seq_length]    , self.num_labels    )
											_lowerCamelCase	:     Dict       =       ids_tensor([self.batch_size]    , self.num_choices    )

							_lowerCamelCase	:     int       =       self.get_config()
							return config, input_ids, input_mask, sequence_labels, token_labels, choice_labels
			def    A_       (    self    ):
							return MPNetConfig(
							    vocab_size=self.vocab_size    , hidden_size=self.hidden_size    , num_hidden_layers=self.num_hidden_layers    , num_attention_heads=self.num_attention_heads    , intermediate_size=self.intermediate_size    , hidden_act=self.hidden_act    , hidden_dropout_prob=self.hidden_dropout_prob    , attention_probs_dropout_prob=self.attention_probs_dropout_prob    , max_position_embeddings=self.max_position_embeddings    , initializer_range=self.initializer_range    , )
			def    A_       (    self    , lowercase    , lowercase    , lowercase    , lowercase    , lowercase    , lowercase    ):
							_lowerCamelCase	:     Optional[Any]       =       MPNetModel(config=lowercase    )
							model.to(lowercase    )
							model.eval()
							_lowerCamelCase	:     Tuple       =       model(lowercase    , lowercase    )
							_lowerCamelCase	:     Tuple       =       model(lowercase    )
							self.parent.assertEqual(result.last_hidden_state.shape    , (self.batch_size, self.seq_length, self.hidden_size)    )
							self.parent.assertEqual(result.pooler_output.shape    , (self.batch_size, self.hidden_size)    )
			def    A_       (    self    , lowercase    , lowercase    , lowercase    , lowercase    , lowercase    , lowercase    ):
							_lowerCamelCase	:     str       =       MPNetForQuestionAnswering(config=lowercase    )
							model.to(lowercase    )
							model.eval()
							_lowerCamelCase	:     str       =       model(
							    lowercase    , attention_mask=lowercase    , start_positions=lowercase    , end_positions=lowercase    , )
							self.parent.assertEqual(result.start_logits.shape    , (self.batch_size, self.seq_length)    )
							self.parent.assertEqual(result.end_logits.shape    , (self.batch_size, self.seq_length)    )
			def    A_       (    self    , lowercase    , lowercase    , lowercase    , lowercase    , lowercase    , lowercase    ):
							_lowerCamelCase	:     Optional[int]       =       self.num_labels
							_lowerCamelCase	:     int       =       MPNetForSequenceClassification(lowercase    )
							model.to(lowercase    )
							model.eval()
							_lowerCamelCase	:     Optional[Any]       =       model(lowercase    , attention_mask=lowercase    , labels=lowercase    )
							self.parent.assertEqual(result.logits.shape    , (self.batch_size, self.num_labels)    )
			def    A_       (    self    , lowercase    , lowercase    , lowercase    , lowercase    , lowercase    , lowercase    ):
							_lowerCamelCase	:     List[str]       =       self.num_choices
							_lowerCamelCase	:     List[str]       =       MPNetForMultipleChoice(config=lowercase    )
							model.to(lowercase    )
							model.eval()
							_lowerCamelCase	:     Union[str, Any]       =       input_ids.unsqueeze(1    ).expand(-1    , self.num_choices    , -1    ).contiguous()
							_lowerCamelCase	:     List[str]       =       input_mask.unsqueeze(1    ).expand(-1    , self.num_choices    , -1    ).contiguous()
							_lowerCamelCase	:     Any       =       model(
							    lowercase    , attention_mask=lowercase    , labels=lowercase    , )
							self.parent.assertEqual(result.logits.shape    , (self.batch_size, self.num_choices)    )
			def    A_       (    self    , lowercase    , lowercase    , lowercase    , lowercase    , lowercase    , lowercase    ):
							_lowerCamelCase	:     Any       =       self.num_labels
							_lowerCamelCase	:     Union[str, Any]       =       MPNetForTokenClassification(config=lowercase    )
							model.to(lowercase    )
							model.eval()
							_lowerCamelCase	:     Union[str, Any]       =       model(lowercase    , attention_mask=lowercase    , labels=lowercase    )
							self.parent.assertEqual(result.logits.shape    , (self.batch_size, self.seq_length, self.num_labels)    )






			def    A_       (    self    ):
							_lowerCamelCase	:     Dict       =       self.prepare_config_and_inputs()
							((_lowerCamelCase),					(_lowerCamelCase),					(_lowerCamelCase),					(_lowerCamelCase),					(_lowerCamelCase),					(_lowerCamelCase))	:     List[Any]       =       config_and_inputs
							_lowerCamelCase	:     str       =       {'input_ids': input_ids, 'attention_mask': input_mask}
							return config, inputs_dict






@require_torch
class lowerCAmelCase__      (	lowercase,      lowercase,      unittest.TestCase		):






			'''simple docstring'''



			lowerCamelCase__ =     (
			    (
			        MPNetForMaskedLM,
			        MPNetForMultipleChoice,
			        MPNetForQuestionAnswering,
			        MPNetForSequenceClassification,
			        MPNetForTokenClassification,
			        MPNetModel,
			    )
			    if is_torch_available()
			    else ()
			)
			lowerCamelCase__ =     (
			    {
			        """feature-extraction""": MPNetModel,
			        """fill-mask""": MPNetForMaskedLM,
			        """question-answering""": MPNetForQuestionAnswering,
			        """text-classification""": MPNetForSequenceClassification,
			        """token-classification""": MPNetForTokenClassification,
			        """zero-shot""": MPNetForSequenceClassification,
			    }
			    if is_torch_available()
			    else {}
			)
			lowerCamelCase__ =     False
			lowerCamelCase__ =     True
			def    A_       (    self    ):
							_lowerCamelCase	:     Union[str, Any]       =       MPNetModelTester(self    )
							_lowerCamelCase	:     List[Any]       =       ConfigTester(self    , config_class=lowercase    , hidden_size=37    )
			def    A_       (    self    ):
							self.config_tester.run_common_tests()
			def    A_       (    self    ):
							_lowerCamelCase	:     Union[str, Any]       =       self.model_tester.prepare_config_and_inputs()
							self.model_tester.create_and_check_mpnet_model(*lowercase    )
			def    A_       (    self    ):
							_lowerCamelCase	:     List[Any]       =       self.model_tester.prepare_config_and_inputs()
							self.model_tester.create_and_check_mpnet_for_sequence_classification(*lowercase    )
			def    A_       (    self    ):
							_lowerCamelCase	:     Optional[Any]       =       self.model_tester.prepare_config_and_inputs()
							self.model_tester.create_and_check_mpnet_for_multiple_choice(*lowercase    )
			def    A_       (    self    ):
							_lowerCamelCase	:     List[Any]       =       self.model_tester.prepare_config_and_inputs()
							self.model_tester.create_and_check_mpnet_for_token_classification(*lowercase    )






			def    A_       (    self    ):
							_lowerCamelCase	:     str       =       self.model_tester.prepare_config_and_inputs()
							self.model_tester.create_and_check_mpnet_for_question_answering(*lowercase    )






@require_torch
class lowerCAmelCase__      (	unittest.TestCase		):






			'''simple docstring'''



			@slow
			def    A_       (    self    ):
							_lowerCamelCase	:     Optional[Any]       =       MPNetModel.from_pretrained('microsoft/mpnet-base'    )
							_lowerCamelCase	:     Optional[Any]       =       torch.tensor([[0, 345, 232, 328, 740, 140, 1695, 69, 6078, 1588, 2]]    )
							_lowerCamelCase	:     Any       =       model(lowercase    )[0]
							_lowerCamelCase	:     Dict       =       torch.Size((1, 11, 768)    )
							self.assertEqual(output.shape    , lowercase    )
							_lowerCamelCase	:     List[Any]       =       torch.tensor(
							    [[[-0.05_50, 0.19_43, -0.07_40], [-0.05_62, 0.22_11, -0.05_79], [-0.04_37, 0.33_37, -0.06_41]]]    )
							# compare the actual values for a slice.
							self.assertTrue(torch.allclose(output[:, :3, :3]    , lowercase    , atol=1E-4    )    )