





import unittest

from transformers import LayoutLMConfig, 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
from ...test_pipeline_mixin import PipelineTesterMixin


if is_torch_available():
				import torch

				from transformers import (
				    LayoutLMForMaskedLM,
				    LayoutLMForQuestionAnswering,
				    LayoutLMForSequenceClassification,
				    LayoutLMForTokenClassification,
				    LayoutLMModel,
				)





class 						_A:


				"""simple docstring"""


				def __init__(      self					, _A					, _A=13					, _A=7					, _A=True					, _A=True					, _A=True					, _A=True					, _A=99					, _A=32					, _A=5					, _A=4					, _A=37					, _A="gelu"					, _A=0.1					, _A=0.1					, _A=512					, _A=16					, _A=2					, _A=0.0_2					, _A=3					, _A=4					, _A=None					, _A=1000					, ):
									__A     :						List[Any]          =    parent
									__A     :						Optional[int]          =    batch_size
									__A     :						Optional[int]          =    seq_length
									__A     :						List[Any]          =    is_training
									__A     :						Dict          =    use_input_mask
									__A     :						Union[str, Any]          =    use_token_type_ids
									__A     :						Union[str, Any]          =    use_labels
									__A     :						Dict          =    vocab_size
									__A     :						List[Any]          =    hidden_size
									__A     :						Optional[Any]          =    num_hidden_layers
									__A     :						Any          =    num_attention_heads
									__A     :						Optional[int]          =    intermediate_size
									__A     :						List[str]          =    hidden_act
									__A     :						int          =    hidden_dropout_prob
									__A     :						Union[str, Any]          =    attention_probs_dropout_prob
									__A     :						Optional[Any]          =    max_position_embeddings
									__A     :						Optional[Any]          =    type_vocab_size
									__A     :						Optional[Any]          =    type_sequence_label_size
									__A     :						Tuple          =    initializer_range
									__A     :						int          =    num_labels
									__A     :						int          =    num_choices
									__A     :						Optional[int]          =    scope
									__A     :						List[Any]          =    range_bbox



				def  UpperCAmelCase_		(      self					):
									__A     :						Optional[int]          =    ids_tensor([self.batch_size, self.seq_length]					, self.vocab_size					)

									__A     :						Any          =    ids_tensor([self.batch_size, self.seq_length, 4]					, self.range_bbox					)
									# Ensure that bbox is legal
									for i in range(bbox.shape[0]					):
														for j in range(bbox.shape[1]					):
																			if bbox[i, j, 3] < bbox[i, j, 1]:
																								__A     :						Union[str, Any]          =    bbox[i, j, 3]
																								__A     :						str          =    bbox[i, j, 1]
																								__A     :						List[Any]          =    t
																			if bbox[i, j, 2] < bbox[i, j, 0]:
																								__A     :						Optional[Any]          =    bbox[i, j, 2]
																								__A     :						str          =    bbox[i, j, 0]
																								__A     :						Tuple          =    t

									__A     :						Any          =    None
									if self.use_input_mask:
														__A     :						Dict          =    ids_tensor([self.batch_size, self.seq_length]					, vocab_size=2					)

									__A     :						str          =    None
									if self.use_token_type_ids:
														__A     :						Optional[Any]          =    ids_tensor([self.batch_size, self.seq_length]					, self.type_vocab_size					)

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

									__A     :						Tuple          =    self.get_config()

									return config, input_ids, bbox, token_type_ids, input_mask, sequence_labels, token_labels, choice_labels



				def  UpperCAmelCase_		(      self					):
									return LayoutLMConfig(
									    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					, type_vocab_size=self.type_vocab_size					, initializer_range=self.initializer_range					, )



				def  UpperCAmelCase_		(      self					, _A					, _A					, _A					, _A					, _A					, _A					, _A					, _A					):
									__A     :						List[str]          =    LayoutLMModel(config=_A					)
									model.to(_A					)
									model.eval()
									__A     :						List[str]          =    model(_A					, _A					, attention_mask=_A					, token_type_ids=_A					)
									__A     :						Dict          =    model(_A					, _A					, token_type_ids=_A					)
									__A     :						str          =    model(_A					, _A					)
									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  UpperCAmelCase_		(      self					, _A					, _A					, _A					, _A					, _A					, _A					, _A					, _A					):
									__A     :						Union[str, Any]          =    LayoutLMForMaskedLM(config=_A					)
									model.to(_A					)
									model.eval()
									__A     :						Tuple          =    model(_A					, _A					, attention_mask=_A					, token_type_ids=_A					, labels=_A					)
									self.parent.assertEqual(result.logits.shape					, (self.batch_size, self.seq_length, self.vocab_size)					)



				def  UpperCAmelCase_		(      self					, _A					, _A					, _A					, _A					, _A					, _A					, _A					, _A					):
									__A     :						int          =    self.num_labels
									__A     :						Any          =    LayoutLMForSequenceClassification(_A					)
									model.to(_A					)
									model.eval()
									__A     :						List[str]          =    model(
									    _A					, _A					, attention_mask=_A					, token_type_ids=_A					, labels=_A					)
									self.parent.assertEqual(result.logits.shape					, (self.batch_size, self.num_labels)					)



				def  UpperCAmelCase_		(      self					, _A					, _A					, _A					, _A					, _A					, _A					, _A					, _A					):
									__A     :						List[Any]          =    self.num_labels
									__A     :						List[Any]          =    LayoutLMForTokenClassification(config=_A					)
									model.to(_A					)
									model.eval()
									__A     :						Any          =    model(_A					, _A					, attention_mask=_A					, token_type_ids=_A					, labels=_A					)
									self.parent.assertEqual(result.logits.shape					, (self.batch_size, self.seq_length, self.num_labels)					)



				def  UpperCAmelCase_		(      self					, _A					, _A					, _A					, _A					, _A					, _A					, _A					, _A					):
									__A     :						Union[str, Any]          =    LayoutLMForQuestionAnswering(config=_A					)
									model.to(_A					)
									model.eval()
									__A     :						int          =    model(
									    _A					, bbox=_A					, attention_mask=_A					, token_type_ids=_A					, start_positions=_A					, end_positions=_A					, )
									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  UpperCAmelCase_		(      self					):
									__A     :						Any          =    self.prepare_config_and_inputs()
									(
									    (
									    __A
									)   ,    (
									    __A
									)   ,    (
									    __A
									)   ,    (
									    __A
									)   ,    (
									    __A
									)   ,    (
									    __A
									)   ,    (
									    __A
									)   ,    (
									    __A
									)   ,    
									)     :						int          =    config_and_inputs
									__A     :						Any          =    {
									    'input_ids': input_ids,
									    'bbox': bbox,
									    'token_type_ids': token_type_ids,
									    'attention_mask': input_mask,
									}
									return config, inputs_dict





@require_torch
class 						_A( snake_case__    ,			snake_case__    ,			unittest.TestCase       ):


				"""simple docstring"""


				UpperCamelCase   :  Optional[int]    =     (
				    (
				        LayoutLMModel,
				        LayoutLMForMaskedLM,
				        LayoutLMForSequenceClassification,
				        LayoutLMForTokenClassification,
				        LayoutLMForQuestionAnswering,
				    )
				    if is_torch_available()
				    else None
				)
				UpperCamelCase   :  Tuple    =     (
				    {
				        '''document-question-answering''': LayoutLMForQuestionAnswering,
				        '''feature-extraction''': LayoutLMModel,
				        '''fill-mask''': LayoutLMForMaskedLM,
				        '''text-classification''': LayoutLMForSequenceClassification,
				        '''token-classification''': LayoutLMForTokenClassification,
				        '''zero-shot''': LayoutLMForSequenceClassification,
				    }
				    if is_torch_available()
				    else {}
				)
				UpperCamelCase   :  List[str]    =     True



				def  UpperCAmelCase_		(      self					):
									__A     :						Union[str, Any]          =    LayoutLMModelTester(self					)
									__A     :						int          =    ConfigTester(self					, config_class=_A					, hidden_size=37					)



				def  UpperCAmelCase_		(      self					):
									self.config_tester.run_common_tests()



				def  UpperCAmelCase_		(      self					):
									__A     :						List[str]          =    self.model_tester.prepare_config_and_inputs()
									self.model_tester.create_and_check_model(*_A					)



				def  UpperCAmelCase_		(      self					):
									__A     :						Any          =    self.model_tester.prepare_config_and_inputs()
									for type in ["absolute", "relative_key", "relative_key_query"]:
														__A     :						str          =    type
														self.model_tester.create_and_check_model(*_A					)



				def  UpperCAmelCase_		(      self					):
									__A     :						Any          =    self.model_tester.prepare_config_and_inputs()
									self.model_tester.create_and_check_for_masked_lm(*_A					)



				def  UpperCAmelCase_		(      self					):
									__A     :						List[Any]          =    self.model_tester.prepare_config_and_inputs()
									self.model_tester.create_and_check_for_sequence_classification(*_A					)



				def  UpperCAmelCase_		(      self					):
									__A     :						int          =    self.model_tester.prepare_config_and_inputs()
									self.model_tester.create_and_check_for_token_classification(*_A					)



				def  UpperCAmelCase_		(      self					):
									__A     :						Union[str, Any]          =    self.model_tester.prepare_config_and_inputs()
									self.model_tester.create_and_check_for_question_answering(*_A					)





				@unittest.skip('Will be fixed soon by reducing the size of the model used for common tests.'					)
				def  UpperCAmelCase_		(      self					):
									pass







def 			_SCREAMING_SNAKE_CASE    (       )				->				Optional[int]:
					# Here we prepare a batch of 2 sequences to test a LayoutLM forward pass on:
					# fmt: off
					__A     :						Dict          =    torch.tensor([[1_01,10_19,10_14,10_16,10_37,1_28_49,47_47,10_04,1_42_46,22_78,54_39,45_24,50_02,29_30,21_93,29_30,43_41,32_08,10_05,10_55,21_71,28_48,1_13_00,35_31,1_02],[1_01,40_70,40_34,70_20,10_24,30_58,10_15,10_13,28_61,10_13,60_70,1_92_74,27_72,62_05,2_78_14,1_61_47,1_61_47,43_43,20_47,1_02_83,1_09_69,1_43_89,10_12,23_38,1_02]] ,						device=a  )  # noqa: E231
					__A     :						List[str]          =    torch.tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],] ,						device=a  )  # noqa: E231
					__A     :						List[Any]          =    torch.tensor([[[0,0,0,0],[4_23,2_37,4_40,2_51],[4_27,2_72,4_41,2_87],[4_19,1_15,4_37,1_29],[9_61,8_85,9_92,9_12],[2_56,38,3_30,58],[2_56,38,3_30,58],[3_36,42,3_53,57],[3_60,39,4_01,56],[3_60,39,4_01,56],[4_11,39,4_71,59],[4_79,41,5_28,59],[5_33,39,6_30,60],[67,1_13,1_34,1_31],[1_41,1_15,2_09,1_32],[68,1_49,1_33,1_66],[1_41,1_49,1_87,1_64],[1_95,1_48,2_87,1_65],[1_95,1_48,2_87,1_65],[1_95,1_48,2_87,1_65],[2_95,1_48,3_49,1_65],[4_41,1_49,4_92,1_66],[4_97,1_49,5_46,1_64],[64,2_01,1_25,2_18],[10_00,10_00,10_00,10_00]],[[0,0,0,0],[6_62,1_50,7_54,1_66],[6_65,1_99,7_42,2_11],[5_19,2_13,5_54,2_28],[5_19,2_13,5_54,2_28],[1_34,4_33,1_87,4_54],[1_30,4_67,2_04,4_80],[1_30,4_67,2_04,4_80],[1_30,4_67,2_04,4_80],[1_30,4_67,2_04,4_80],[1_30,4_67,2_04,4_80],[3_14,4_69,3_76,4_82],[5_04,6_84,5_82,7_06],[9_41,8_25,9_73,9_00],[9_41,8_25,9_73,9_00],[9_41,8_25,9_73,9_00],[9_41,8_25,9_73,9_00],[6_10,7_49,6_52,7_65],[1_30,6_59,1_68,6_72],[1_76,6_57,2_37,6_72],[2_38,6_57,3_12,6_72],[4_43,6_53,6_28,6_72],[4_43,6_53,6_28,6_72],[7_16,3_01,8_25,3_17],[10_00,10_00,10_00,10_00]]] ,						device=a  )  # noqa: E231
					__A     :						List[Any]          =    torch.tensor([[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]] ,						device=a  )  # noqa: E231
					# these are sequence labels (i.e. at the token level)
					__A     :						int          =    torch.tensor([[-1_00,10,10,10,9,1,-1_00,7,7,-1_00,7,7,4,2,5,2,8,8,-1_00,-1_00,5,0,3,2,-1_00],[-1_00,12,12,12,-1_00,12,10,-1_00,-1_00,-1_00,-1_00,10,12,9,-1_00,-1_00,-1_00,10,10,10,9,12,-1_00,10,-1_00]] ,						device=a  )  # noqa: E231
					# fmt: on

					return input_ids, attention_mask, bbox, token_type_ids, labels





@require_torch
class 						_A( unittest.TestCase       ):


				"""simple docstring"""


				@slow
				def  UpperCAmelCase_		(      self					):
									__A     :						Optional[int]          =    LayoutLMModel.from_pretrained('microsoft/layoutlm-base-uncased'					).to(_A					)

									__A   ,    __A   ,    __A   ,    __A   ,    __A     :						Any          =    prepare_layoutlm_batch_inputs()

									# forward pass
									__A     :						int          =    model(input_ids=_A					, bbox=_A					, attention_mask=_A					, token_type_ids=_A					)

									# test the sequence output on [0, :3, :3]
									__A     :						str          =    torch.tensor(
									    [[0.1_7_8_5, -0.1_9_4_7, -0.0_4_2_5], [-0.3_2_5_4, -0.2_8_0_7, 0.2_5_5_3], [-0.5_3_9_1, -0.3_3_2_2, 0.3_3_6_4]]					, device=_A					, )

									self.assertTrue(torch.allclose(outputs.last_hidden_state[0, :3, :3]					, _A					, atol=1e-3					)					)

									# test the pooled output on [1, :3]
									__A     :						Tuple          =    torch.tensor([-0.6_5_8_0, -0.0_2_1_4, 0.8_5_5_2]					, device=_A					)

									self.assertTrue(torch.allclose(outputs.pooler_output[1, :3]					, _A					, atol=1e-3					)					)



				@slow
				def  UpperCAmelCase_		(      self					):
									# initialize model with randomly initialized sequence classification head
									__A     :						Optional[int]          =    LayoutLMForSequenceClassification.from_pretrained('microsoft/layoutlm-base-uncased'					, num_labels=2					).to(
									    _A					)

									__A   ,    __A   ,    __A   ,    __A   ,    __A     :						List[Any]          =    prepare_layoutlm_batch_inputs()

									# forward pass
									__A     :						Union[str, Any]          =    model(
									    input_ids=_A					, bbox=_A					, attention_mask=_A					, token_type_ids=_A					, labels=torch.tensor([1, 1]					, device=_A					)					, )

									# test whether we get a loss as a scalar
									__A     :						Any          =    outputs.loss
									__A     :						str          =    torch.Size([]					)
									self.assertEqual(loss.shape					, _A					)

									# test the shape of the logits
									__A     :						Optional[int]          =    outputs.logits
									__A     :						Optional[Any]          =    torch.Size((2, 2)					)
									self.assertEqual(logits.shape					, _A					)



				@slow
				def  UpperCAmelCase_		(      self					):
									# initialize model with randomly initialized token classification head
									__A     :						Optional[Any]          =    LayoutLMForTokenClassification.from_pretrained('microsoft/layoutlm-base-uncased'					, num_labels=13					).to(
									    _A					)

									__A   ,    __A   ,    __A   ,    __A   ,    __A     :						Any          =    prepare_layoutlm_batch_inputs()

									# forward pass
									__A     :						Optional[int]          =    model(
									    input_ids=_A					, bbox=_A					, attention_mask=_A					, token_type_ids=_A					, labels=_A					)

									# test the loss calculation to be around 2.65
									# expected_loss = torch.tensor(2.65, device=torch_device)

									# The loss is currently somewhat random and can vary between 0.1-0.3 atol.
									# self.assertTrue(torch.allclose(outputs.loss, expected_loss, atol=0.1))

									# test the shape of the logits
									__A     :						List[Any]          =    outputs.logits
									__A     :						Dict          =    torch.Size((2, 25, 13)					)
									self.assertEqual(logits.shape					, _A					)





				@slow
				def  UpperCAmelCase_		(      self					):
									# initialize model with randomly initialized token classification head
									__A     :						int          =    LayoutLMForQuestionAnswering.from_pretrained('microsoft/layoutlm-base-uncased'					).to(_A					)

									__A   ,    __A   ,    __A   ,    __A   ,    __A     :						Optional[Any]          =    prepare_layoutlm_batch_inputs()

									# forward pass
									__A     :						Optional[Any]          =    model(input_ids=_A					, bbox=_A					, attention_mask=_A					, token_type_ids=_A					)

									# test the shape of the logits
									__A     :						List[str]          =    torch.Size((2, 25)					)
									self.assertEqual(outputs.start_logits.shape					, _A					)
									self.assertEqual(outputs.end_logits.shape					, _A					)











import logging
from pathlib import Path
from typing import Any, List, Tuple

import yaml


# loading package files: https://stackoverflow.com/a/20885799
try:
				import importlib.resources as pkg_resources
except ImportError:
				# Try backported to PY<37 `importlib_resources`.
				import importlib_resources as pkg_resources

from . import resources


UpperCAmelCase						:       Optional[Any]        =					'''https://github.com/huggingface/datasets/tree/main/src/datasets/utils'''
UpperCAmelCase						:       Any        =					F"""{BASE_REF_URL}/{__file__}"""
UpperCAmelCase						:       int        =					logging.getLogger(__name__)







def 			_SCREAMING_SNAKE_CASE    (       a  )				->				Tuple[Any, str]:
					__A     :						List[Any]          =    pkg_resources.read_text(a ,						a  )
					return yaml.safe_load(a  ), F"""{BASE_REF_URL}/resources/{resource}"""


UpperCAmelCase  ,			UpperCAmelCase						:       Tuple        =					load_yaml_resource('''readme_structure.yaml''')

UpperCAmelCase						:       List[Any]        =					[
    '''[Needs More Information]''',
    '''[More Information Needed]''',
    '''(https://github.com/huggingface/datasets/blob/main/CONTRIBUTING.md#how-to-contribute-to-the-dataset-cards)''',
]

# Dictionary representation of section/readme, error_list, warning_list
UpperCAmelCase						:       Union[str, Any]        =					Tuple[dict, List[str], List[str]]





class 						_A:


				"""simple docstring"""


				def __init__(      self					, _A					, _A					, _A = None					, _A = False					):
									__A     :						Dict          =    name
									__A     :						str          =    level
									__A     :						List[str]          =    lines
									__A     :						List[Any]          =    ''
									__A     :						Optional[Any]          =    True
									__A     :						List[Any]          =    {}
									__A     :						Optional[Any]          =    []
									__A     :						Optional[int]          =    []
									if self.lines is not None:
														self.parse(suppress_parsing_errors=_A					)



				def  UpperCAmelCase_		(      self					, _A = False					):
									__A     :						Any          =    ''
									__A     :						Union[str, Any]          =    []
									__A     :						Tuple          =    False
									for line in self.lines:
														if line.strip(' \n'					) == "":
																			continue
														elif line.strip(' \n'					)[:3] == "```":
																			__A     :						int          =    not code_start
														elif line.split()[0] == self.level + "#" and not code_start:
																			if current_sub_level != "":
																								__A     :						Dict          =    Section(_A					, self.level + '#'					, _A					)
																								__A     :						Optional[int]          =    []
																			else:
																								if current_lines != []:
																													self.text += "".join(_A					).strip()
																													if self.text != "" and self.text not in FILLER_TEXT:
																																		__A     :						Union[str, Any]          =    False
																													__A     :						Dict          =    []

																			__A     :						Optional[Any]          =    ' '.join(line.split()[1:]					).strip(' \n'					)
														else:
																			current_lines.append(_A					)
									else:
														if current_sub_level != "":
																			if current_sub_level in self.content:
																								self.parsing_error_list.append(
																								    F"""Multiple sections with the same heading `{current_sub_level}` have been found. Please keep only one of these sections."""					)
																			__A     :						Any          =    Section(_A					, self.level + '#'					, _A					)
														else:
																			if current_lines != []:
																								self.text += "".join(_A					).strip()
																								if self.text != "" and self.text not in FILLER_TEXT:
																													__A     :						str          =    False

									if self.level == "" and not suppress_parsing_errors:
														if self.parsing_error_list != [] or self.parsing_warning_list != []:
																			__A     :						Optional[int]          =    '\n'.join('-\t' + x for x in self.parsing_error_list + self.parsing_warning_list					)
																			__A     :						List[Any]          =    F"""The following issues were found while parsing the README at `{self.name}`:\n""" + errors
																			raise ValueError(_A					)



				def  UpperCAmelCase_		(      self					, _A					):
									__A     :						Any          =    []
									__A     :						Tuple          =    []
									if structure["allow_empty"] is False:
														# If content is expected
														if self.is_empty_text and self.content == {}:
																			# If no content is found, mention it in the error_list
																			error_list.append(F"""Expected some content in section `{self.name}` but it is empty."""					)

									if structure["allow_empty_text"] is False:
														# If some text is expected
														if self.is_empty_text:
																			# If no text is found, mention it in the error_list
																			error_list.append(
																			    F"""Expected some text in section `{self.name}` but it is empty (text in subsections are ignored)."""					)
        # Subsections Validation
									if structure["subsections"] is not None:
														# If subsections are expected
														if self.content == {}:
																			# If no subsections are present
																			__A     :						int          =    [subsection['name'] for subsection in structure['subsections']]
																			# Mention the expected values in the error_list
																			error_list.append(
																			    F"""Section `{self.name}` expected the following subsections: {", ".join(["`"+x+"`" for x in values]					)}. Found 'None'."""					)
														else:
																			# If some subsections are present
																			__A     :						Optional[Any]          =    [subsection['name'] for subsection in structure['subsections']]
																			__A     :						str          =    False
																			for idx, name in enumerate(_A					):
																								if name not in self.content:
																													# If the expected subsection is not present
																													error_list.append(F"""Section `{self.name}` is missing subsection: `{name}`."""					)
																													__A     :						Optional[Any]          =    True
																								else:
																													# If the subsection is present, validate subsection, return the result
																													# and concat the errors from subsection to section error_list

																													# Skip sublevel validation if current level is `###`
																													if self.level == "###":
																																		continue
																													else:
																																		__A   ,    __A   ,    __A     :						Optional[int]          =    self.content[name].validate(
																																		    structure['subsections'][idx]					)
																													error_list += subsec_error_list
																													warning_list += subsec_warning_list

																			if has_missing_subsections:  # we only allow to have extra subsections if all the other ones are here
																								for name in self.content:
																													if name not in structure_names:
																																		# If an extra subsection is present
																																		warning_list.append(
																																		    F"""`{self.name}` has an extra subsection: `{name}`. Skipping further validation checks for this subsection as expected structure is unknown."""					)
									if error_list:
														# If there are errors, do not return the dictionary as it is invalid
														return {}, error_list, warning_list
									else:
														return self.to_dict(), error_list, warning_list





				def  UpperCAmelCase_		(      self					):
									return {
									    "name": self.name,
									    "text": self.text,
									    "is_empty_text": self.is_empty_text,
									    "subsections": [value.to_dict() for value in self.content.values()],
									}





class 						_A( snake_case__       ):  # Level 0


				"""simple docstring"""


				def __init__(      self					, _A					, _A					, _A = None					, _A = False					):
									super().__init__(name=_A					, level=''					)  # Not using lines here as we need to use a child class parse
									__A     :						List[str]          =    structure
									__A     :						str          =    -2
									__A     :						Tuple          =    0
									__A     :						Dict          =    lines
									if self.lines is not None:
														self.parse(suppress_parsing_errors=_A					)



				def  UpperCAmelCase_		(      self					):
									if self.structure is None:
														__A   ,    __A   ,    __A     :						List[Any]          =    self._validate(_A					)
									else:
														__A   ,    __A   ,    __A     :						Any          =    self._validate(self.structure					)
									if error_list != [] or warning_list != []:
														__A     :						Optional[Any]          =    '\n'.join(['-\t' + x for x in error_list + warning_list]					)
														__A     :						Union[str, Any]          =    F"""The following issues were found for the README at `{self.name}`:\n""" + errors
														raise ValueError(_A					)



				@classmethod
				def  UpperCAmelCase_		(      cls					, _A					, _A = None					, _A = False					):
									with open(_A					, encoding='utf-8'					) as f:
														__A     :						str          =    f.readlines()
									return cls(_A					, _A					, _A					, suppress_parsing_errors=_A					)



				@classmethod
				def  UpperCAmelCase_		(      cls					, _A					, _A = None					, _A = "root"					, _A = False					):
									__A     :						Any          =    string.split('\n'					)
									return cls(_A					, _A					, _A					, suppress_parsing_errors=_A					)



				def  UpperCAmelCase_		(      self					, _A = False					):
									# Skip Tags
									__A     :						Any          =    0

									for line in self.lines:
														self.yaml_tags_line_count += 1
														if line.strip(' \n'					) == "---":
																			self.tag_count += 1
																			if self.tag_count == 2:
																								break
														line_count += 1
									if self.tag_count == 2:
														__A     :						List[str]          =    self.lines[line_count + 1 :]  # Get the last + 1 th item.
									else:
														__A     :						List[Any]          =    self.lines[self.tag_count :]
									super().parse(suppress_parsing_errors=_A					)



				def __str__(      self					):
									return str(self.to_dict()					)





				def  UpperCAmelCase_		(      self					, _A					):
									__A     :						List[str]          =    []
									__A     :						List[Any]          =    []
									if self.yaml_tags_line_count == 0:
														warning_list.append('Empty YAML markers are present in the README.'					)
									elif self.tag_count == 0:
														warning_list.append('No YAML markers are present in the README.'					)
									elif self.tag_count == 1:
														warning_list.append('Only the start of YAML tags present in the README.'					)
									# Check how many first level sections are present.
									__A     :						Optional[int]          =    len(self.content.keys()					)
									if num_first_level_keys > 1:
														# If more than one, add to the error list, continue
														error_list.append(
														    F"""The README has several first-level headings: {", ".join(["`"+x+"`" for x in list(self.content.keys()					)]					)}. Only one heading is expected. Skipping further validation for this README."""					)
									elif num_first_level_keys < 1:
														# If less than one, append error.
														error_list.append(
														    'The README has no first-level headings. One heading is expected. Skipping further validation for this README.'					)

									else:
														# If one exactly
														__A     :						List[Any]          =    list(self.content.keys()					)[0]  # Get the key
														if start_key.startswith('Dataset Card for'					):  # Check correct start
																			# If the starting is correct, validate all the sections
																			__A   ,    __A   ,    __A     :						List[str]          =    self.content[start_key].validate(
																			    readme_structure['subsections'][0]					)
																			error_list += sec_error_list
																			warning_list += sec_warning_list
														else:
																			# If not found, append error
																			error_list.append(
																			    'No first-level heading starting with `Dataset Card for` found in README. Skipping further validation for this README.'					)
									if error_list:
														# If there are errors, do not return the dictionary as it is invalid
														return {}, error_list, warning_list
									else:
														return self.to_dict(), error_list, warning_list


if __name__ == "__main__":
				from argparse import ArgumentParser

				UpperCAmelCase						:       Dict        =					ArgumentParser(usage='''Validate the content (excluding YAML tags) of a README.md file.''')
				ap.add_argument('''readme_filepath''')
				UpperCAmelCase						:       Tuple        =					ap.parse_args()
				UpperCAmelCase						:       List[str]        =					Path(args.readme_filepath)
				UpperCAmelCase						:       int        =					ReadMe.from_readme(readme_filepath)




