import collections
import importlib.util
import os
import re
from pathlib import Path


A_      =      "src/transformers"


# Matches is_xxx_available()
A_      =      re.compile(R"is\_([a-z_]*)_available()")
# Catches a one-line _import_struct = {xxx}
A_      =      re.compile(R"^_import_structure\s+=\s+\{([^\}]+)\}")
# Catches a line with a key-values pattern: "bla": ["foo", "bar"]
A_      =      re.compile(R"\s+\"\S*\":\s+\[([^\]]*)\]")
# Catches a line if not is_foo_available
A_      =      re.compile(R"^\s*if\s+not\s+is\_[a-z_]*\_available\(\)")
# Catches a line _import_struct["bla"].append("foo")
A_      =      re.compile(R"^\s*_import_structure\[\"\S*\"\]\.append\(\"(\S*)\"\)")
# Catches a line _import_struct["bla"].extend(["foo", "bar"]) or _import_struct["bla"] = ["foo", "bar"]
A_      =      re.compile(R"^\s*_import_structure\[\S*\](?:\.extend\(|\s*=\s+)\[([^\]]*)\]")
# Catches a line with an object between quotes and a comma:     "MyModel",
A_      =      re.compile("^\s+\"([^\"]+)\",")
# Catches a line with objects between brackets only:    ["foo", "bar"],
A_      =      re.compile("^\s+\[([^\]]+)\]")
# Catches a line with from foo import bar, bla, boo
A_      =      re.compile(R"\s+from\s+\S*\s+import\s+([^\(\s].*)\n")
# Catches a line with try:
A_      =      re.compile(R"^\s*try:")
# Catches a line with else:
A_      =      re.compile(R"^\s*else:")






def        __UpperCAmelCase    (       UpperCAmelCase       )->       Optional[Any]:



			"""simple docstring"""







			if _re_test_backend.search(UpperCAmelCase       ) is None:
						return None
			lowercase							=		[b[0] for b in _re_backend.findall(UpperCAmelCase       )]
			backends.sort()
			return "_and_".join(UpperCAmelCase       )






def        __UpperCAmelCase    (       UpperCAmelCase       )->       Optional[int]:



			"""simple docstring"""







			with open(UpperCAmelCase,		'''r''',		encoding='''utf-8''',		newline='''\n'''       ) as f:
						lowercase							=		f.readlines()

			lowercase							=		0
			while line_index < len(UpperCAmelCase       ) and not lines[line_index].startswith('''_import_structure = {'''       ):
						line_index += 1

			# If this is a traditional init, just return.
			if line_index >= len(UpperCAmelCase       ):
						return None

			# First grab the objects without a specific backend in _import_structure
			lowercase							=		[]
			while not lines[line_index].startswith('''if TYPE_CHECKING'''       ) and find_backend(lines[line_index]       ) is None:
						lowercase							=		lines[line_index]
						# If we have everything on a single line, let's deal with it.
						if _re_one_line_import_struct.search(UpperCAmelCase       ):
									lowercase							=		_re_one_line_import_struct.search(UpperCAmelCase       ).groups()[0]
									lowercase							=		re.findall('''\[([^\]]+)\]''',		UpperCAmelCase       )
									for imp in imports:
												objects.extend([obj[1:-1] for obj in imp.split(''', '''       )]       )
									line_index += 1
									continue
						lowercase							=		_re_import_struct_key_value.search(UpperCAmelCase       )
						if single_line_import_search is not None:
									lowercase							=		[obj[1:-1] for obj in single_line_import_search.groups()[0].split(''', '''       ) if len(UpperCAmelCase       ) > 0]
									objects.extend(UpperCAmelCase       )
						elif line.startswith(''' ''' * 8 + '''"'''       ):
									objects.append(line[9:-3]       )
						line_index += 1

			lowercase							=		{'''none''': objects}
			# Let's continue with backend-specific objects in _import_structure
			while not lines[line_index].startswith('''if TYPE_CHECKING'''       ):
						# If the line is an if not is_backend_available, we grab all objects associated.
						lowercase							=		find_backend(lines[line_index]       )
						# Check if the backend declaration is inside a try block:
						if _re_try.search(lines[line_index - 1]       ) is None:
									lowercase							=		None

						if backend is not None:
									line_index += 1

									# Scroll until we hit the else block of try-except-else
									while _re_else.search(lines[line_index]       ) is None:
												line_index += 1

									line_index += 1

									lowercase							=		[]
									# Until we unindent, add backend objects to the list
									while len(lines[line_index]       ) <= 1 or lines[line_index].startswith(''' ''' * 4       ):
												lowercase							=		lines[line_index]
												if _re_import_struct_add_one.search(UpperCAmelCase       ) is not None:
															objects.append(_re_import_struct_add_one.search(UpperCAmelCase       ).groups()[0]       )
												elif _re_import_struct_add_many.search(UpperCAmelCase       ) is not None:
															lowercase							=		_re_import_struct_add_many.search(UpperCAmelCase       ).groups()[0].split(''', '''       )
															lowercase							=		[obj[1:-1] for obj in imports if len(UpperCAmelCase       ) > 0]
															objects.extend(UpperCAmelCase       )
												elif _re_between_brackets.search(UpperCAmelCase       ) is not None:
															lowercase							=		_re_between_brackets.search(UpperCAmelCase       ).groups()[0].split(''', '''       )
															lowercase							=		[obj[1:-1] for obj in imports if len(UpperCAmelCase       ) > 0]
															objects.extend(UpperCAmelCase       )
												elif _re_quote_object.search(UpperCAmelCase       ) is not None:
															objects.append(_re_quote_object.search(UpperCAmelCase       ).groups()[0]       )
												elif line.startswith(''' ''' * 8 + '''"'''       ):
															objects.append(line[9:-3]       )
												elif line.startswith(''' ''' * 12 + '''"'''       ):
															objects.append(line[13:-3]       )
												line_index += 1

									lowercase							=		objects
						else:
									line_index += 1

    # At this stage we are in the TYPE_CHECKING part, first grab the objects without a specific backend
			lowercase							=		[]
			while (
			    line_index < len(UpperCAmelCase       )
			    and find_backend(lines[line_index]       ) is None
			    and not lines[line_index].startswith('''else'''       )
			):
						lowercase							=		lines[line_index]
						lowercase							=		_re_import.search(UpperCAmelCase       )
						if single_line_import_search is not None:
									objects.extend(single_line_import_search.groups()[0].split(''', '''       )       )
						elif line.startswith(''' ''' * 8       ):
									objects.append(line[8:-2]       )
						line_index += 1

			lowercase							=		{'''none''': objects}
			# Let's continue with backend-specific objects
			while line_index < len(UpperCAmelCase       ):
						# If the line is an if is_backend_available, we grab all objects associated.
						lowercase							=		find_backend(lines[line_index]       )
						# Check if the backend declaration is inside a try block:
						if _re_try.search(lines[line_index - 1]       ) is None:
									lowercase							=		None

						if backend is not None:
									line_index += 1

									# Scroll until we hit the else block of try-except-else
									while _re_else.search(lines[line_index]       ) is None:
												line_index += 1

									line_index += 1

									lowercase							=		[]
									# Until we unindent, add backend objects to the list
									while len(lines[line_index]       ) <= 1 or lines[line_index].startswith(''' ''' * 8       ):
												lowercase							=		lines[line_index]
												lowercase							=		_re_import.search(UpperCAmelCase       )
												if single_line_import_search is not None:
															objects.extend(single_line_import_search.groups()[0].split(''', '''       )       )
												elif line.startswith(''' ''' * 12       ):
															objects.append(line[12:-2]       )
												line_index += 1

									lowercase							=		objects
						else:
									line_index += 1

			return import_dict_objects, type_hint_objects






def        __UpperCAmelCase    (       UpperCAmelCase,		UpperCAmelCase       )->       Optional[int]:



			"""simple docstring"""







			def find_duplicates(UpperCAmelCase       ):
						return [k for k, v in collections.Counter(UpperCAmelCase       ).items() if v > 1]

			if list(import_dict_objects.keys()       ) != list(type_hint_objects.keys()       ):
						return ["Both sides of the init do not have the same backends!"]

			lowercase							=		[]
			for key in import_dict_objects.keys():
						lowercase							=		find_duplicates(import_dict_objects[key]       )
						if duplicate_imports:
									errors.append(f'Duplicate _import_structure definitions for: {duplicate_imports}'       )
						lowercase							=		find_duplicates(type_hint_objects[key]       )
						if duplicate_type_hints:
									errors.append(f'Duplicate TYPE_CHECKING objects for: {duplicate_type_hints}'       )

						if sorted(set(import_dict_objects[key]       )       ) != sorted(set(type_hint_objects[key]       )       ):
									lowercase							=		'''base imports''' if key == '''none''' else f'{key} backend'
									errors.append(f'Differences for {name}:'       )
									for a in type_hint_objects[key]:
												if a not in import_dict_objects[key]:
															errors.append(f'  {a} in TYPE_HINT but not in _import_structure.'       )
									for a in import_dict_objects[key]:
												if a not in type_hint_objects[key]:
															errors.append(f'  {a} in _import_structure but not in TYPE_HINT.'       )
			return errors






def        __UpperCAmelCase    (       )->       int:



			"""simple docstring"""







			lowercase							=		[]
			for root, _, files in os.walk(UpperCAmelCase       ):
						if "__init__.py" in files:
									lowercase							=		os.path.join(UpperCAmelCase,		'''__init__.py'''       )
									lowercase							=		parse_init(UpperCAmelCase       )
									if objects is not None:
												lowercase							=		analyze_results(*UpperCAmelCase       )
												if len(UpperCAmelCase       ) > 0:
															lowercase							=		f'Problem in {fname}, both halves do not define the same objects.\n{errors[0]}'
															failures.append('''\n'''.join(UpperCAmelCase       )       )
			if len(UpperCAmelCase       ) > 0:
						raise ValueError('''\n\n'''.join(UpperCAmelCase       )       )






def        __UpperCAmelCase    (       )->       int:



			"""simple docstring"""







			lowercase							=		[]
			for path, directories, files in os.walk(UpperCAmelCase       ):
						for folder in directories:
									# Ignore private modules
									if folder.startswith('''_'''       ):
												directories.remove(UpperCAmelCase       )
												continue
									# Ignore leftovers from branches (empty folders apart from pycache)
									if len(list((Path(UpperCAmelCase       ) / folder).glob('''*.py'''       )       )       ) == 0:
												continue
									lowercase							=		str((Path(UpperCAmelCase       ) / folder).relative_to(UpperCAmelCase       )       )
									lowercase							=		short_path.replace(os.path.sep,		'''.'''       )
									submodules.append(UpperCAmelCase       )
						for fname in files:
									if fname == "__init__.py":
												continue
									lowercase							=		str((Path(UpperCAmelCase       ) / fname).relative_to(UpperCAmelCase       )       )
									lowercase							=		short_path.replace('''.py''',		''''''       ).replace(os.path.sep,		'''.'''       )
									if len(submodule.split('''.'''       )       ) == 1:
												submodules.append(UpperCAmelCase       )
			return submodules


A_      =      [
    "convert_pytorch_checkpoint_to_tf2",
    "modeling_flax_pytorch_utils",
]






def        __UpperCAmelCase    (       )->       Tuple:



			"""simple docstring"""







			lowercase							=		importlib.util.spec_from_file_location(
			    '''transformers''',		os.path.join(UpperCAmelCase,		'''__init__.py'''       ),		submodule_search_locations=[PATH_TO_TRANSFORMERS],		)
			lowercase							=		spec.loader.load_module()

			lowercase							=		[
			    module
			    for module in get_transformers_submodules()
			    if module not in IGNORE_SUBMODULES and module not in transformers._import_structure.keys()
			]
			if len(UpperCAmelCase       ) > 0:
						lowercase							=		'''\n'''.join(f'- {module}' for module in module_not_registered       )
						raise ValueError(
						    '''The following submodules are not properly registered in the main init of Transformers:\n'''
						    f'{list_of_modules}\n'
						    '''Make sure they appear somewhere in the keys of `_import_structure` with an empty list as value.'''       )


if __name__ == "__main__":
						check_all_inits()
						check_submodules()






# Lint as: python3
import dataclasses
import re
from dataclasses import dataclass
from functools import total_ordering
from typing import Optional, Union


A_      =      re.compile(R"^(?P<major>\d+)" R"\.(?P<minor>\d+)" R"\.(?P<patch>\d+)$")






@total_ordering
@dataclass
class      __lowercase					:
						lowercase					 =     42
						lowercase					 =     None
						lowercase					 =     None
						lowercase					 =     None
						lowercase					 =     None

						def        __a		(	self				:      int   )							->		str:


									'''simple docstring'''

									lowercase		,lowercase		,lowercase							=		_str_to_version_tuple(self.version_str   )

						def __repr__(	self				:      Union[str, Any]   )							->		int:


									'''simple docstring'''

									return f'{self.tuple[0]}.{self.tuple[1]}.{self.tuple[2]}'

						@property
						def        __a		(	self				:      Dict   )							->		Union[str, Any]:


									'''simple docstring'''

									return self.major, self.minor, self.patch

						def        __a		(	self				:      Optional[Any]							,							__lowerCamelCase				:      Any   )							->		Dict:


									'''simple docstring'''

									if isinstance(__lowerCamelCase							,							__lowerCamelCase   ):
												return Version(__lowerCamelCase   )
									elif isinstance(__lowerCamelCase							,							__lowerCamelCase   ):
												return other
									raise TypeError(f'{other} (type {type(__lowerCamelCase   )}) cannot be compared to version.'   )

						def __eq__(	self				:      Tuple							,							__lowerCamelCase				:      Tuple   )							->		List[Any]:


									'''simple docstring'''

									try:
												lowercase							=		self._validate_operand(__lowerCamelCase   )
									except (TypeError, ValueError):
												return False
									else:
												return self.tuple == other.tuple

						def __lt__(	self				:      Any							,							__lowerCamelCase				:      Union[str, Any]   )							->		int:


									'''simple docstring'''

									lowercase							=		self._validate_operand(__lowerCamelCase   )
									return self.tuple < other.tuple

						def __hash__(	self				:      int   )							->		str:


									'''simple docstring'''

									return hash(_version_tuple_to_str(self.tuple   )   )

						@classmethod
						def        __a		(	cls				:      List[str]							,							__lowerCamelCase				:      Any   )							->		int:


									'''simple docstring'''

									lowercase							=		{f.name for f in dataclasses.fields(cls   )}
									return cls(**{k: v for k, v in dic.items() if k in field_names}   )



						def        __a		(	self				:      Union[str, Any]   )							->		str:


									'''simple docstring'''

									return self.version_str






def        __UpperCAmelCase    (       UpperCAmelCase       )->       List[str]:



			"""simple docstring"""







			lowercase							=		_VERSION_REG.match(UpperCAmelCase       )
			if not res:
						raise ValueError(f'Invalid version \'{version_str}\'. Format should be x.y.z with {{x,y,z}} being digits.'       )
			return tuple(int(UpperCAmelCase       ) for v in [res.group('''major'''       ), res.group('''minor'''       ), res.group('''patch'''       )]       )






def        __UpperCAmelCase    (       UpperCAmelCase       )->       int:



			"""simple docstring"""







			return ".".join(str(UpperCAmelCase       ) for v in version_tuple       )





