



import logging
import os
import threading
import time


try:
	import warnings
except ImportError:
	UpperCAmelCase							 =					None

try:
	import msvcrt
except ImportError:
	UpperCAmelCase							 =					None

try:
	import fcntl
except ImportError:
	UpperCAmelCase							 =					None


# Backward compatibility
# ------------------------------------------------
try:
	TimeoutError
except NameError:
	UpperCAmelCase							 =					OSError


# Data
# ------------------------------------------------
UpperCAmelCase							 =					[
    """Timeout""",
    """BaseFileLock""",
    """WindowsFileLock""",
    """UnixFileLock""",
    """SoftFileLock""",
    """FileLock""",
]

UpperCAmelCase							 =					"""3.0.12"""


UpperCAmelCase							 =					None

def 			A_      (	):

				"""simple docstring"""
				global _logger
				a__				      =		_logger or logging.getLogger(__name__		)
				return _logger

class  __snake_case      (   SCREAMING_SNAKE_CASE):







							'''simple docstring'''






							def __init__(							self  ,  a_		):
											a__				      =		lock_file
											return None







							def __str__(							self		):
											a__				      =		F'''The file lock \'{self.lock_file}\' could not be acquired.'''
											return temp




class  __snake_case      :







							'''simple docstring'''






							def __init__(							self  ,  a_		):
											a__				      =		lock
											return None


							def __enter__(							self		):
											return self.lock







							def __exit__(							self  ,  a_  ,  a_  ,  a_		):
											self.lock.release()
											return None




class  __snake_case      :







							'''simple docstring'''






							def __init__(							self  ,  a_  ,  a_=-1  ,  a_=None		):
											a__				      =		max_filename_length if max_filename_length is not None else 255
											# Hash the filename if it's too long
											a__				      =		self.hash_filename_if_too_long(a_  ,  a_		)
											# The path to the lock file.
											a__				      =		lock_file

											# The file descriptor for the *_lock_file* as it is returned by the
											# os.open() function.
											# This file lock is only NOT None, if the object currently holds the
											# lock.
											a__				      =		None

											# The default timeout value.
											a__				      =		timeout

											# We use this lock primarily for the lock counter.
											a__				      =		threading.Lock()

											# The lock counter is used for implementing the nested locking
											# mechanism. Whenever the lock is acquired, the counter is increased and
											# the lock is only released, when this value is 0 again.
											a__				      =		0
											return None


							@property
							def _a      (							self		):
											return self._lock_file


							@property
							def _a      (							self		):
											return self._timeout


							@timeout.setter
							def _a      (							self  ,  a_		):
											a__				      =		float(a_		)
											return None


							def _a      (							self		):
											raise NotImplementedError()


							def _a      (							self		):
											raise NotImplementedError()


							@property
							def _a      (							self		):
											return self._lock_file_fd is not None


							def _a      (							self  ,  a_=None  ,  a_=0.05		):
											# Use the default timeout, if no timeout is provided.
											if timeout is None:
															a__				      =		self.timeout

											# Increment the number right at the beginning.
											# We can still undo it, if something fails.
											with self._thread_lock:
															self._lock_counter += 1

											a__				      =		id(self		)
											a__				      =		self._lock_file
											a__				      =		time.time()
											try:
															while True:
																			with self._thread_lock:
																							if not self.is_locked:
																											logger().debug(F'''Attempting to acquire lock {lock_id} on {lock_filename}'''		)
																											self._acquire()

																			if self.is_locked:
																							logger().debug(F'''Lock {lock_id} acquired on {lock_filename}'''		)
																							break
																			elif timeout >= 0 and time.time() - start_time > timeout:
																							logger().debug(F'''Timeout on acquiring lock {lock_id} on {lock_filename}'''		)
																							raise Timeout(self._lock_file		)
																			else:
																							logger().debug(
																							    F'''Lock {lock_id} not acquired on {lock_filename}, waiting {poll_intervall} seconds ...'''		)
																							time.sleep(a_		)
											except:  # noqa
															# Something did go wrong, so decrement the counter.
															with self._thread_lock:
																			a__				      =		max(0  ,  self._lock_counter - 1		)

															raise
											return _Acquire_ReturnProxy(lock=self		)


							def _a      (							self  ,  a_=False		):
											with self._thread_lock:
															if self.is_locked:
																			self._lock_counter -= 1

																			if self._lock_counter == 0 or force:
																							a__				      =		id(self		)
																							a__				      =		self._lock_file

																							logger().debug(F'''Attempting to release lock {lock_id} on {lock_filename}'''		)
																							self._release()
																							a__				      =		0
																							logger().debug(F'''Lock {lock_id} released on {lock_filename}'''		)

											return None


							def __enter__(							self		):
											self.acquire()
											return self


							def __exit__(							self  ,  a_  ,  a_  ,  a_		):
											self.release()
											return None


							def __del__(							self		):
											self.release(force=a_		)
											return None







							def _a      (							self  ,  a_  ,  a_		):
											a__				      =		os.path.basename(a_		)
											if len(a_		) > max_length and max_length > 0:
															a__				      =		os.path.dirname(a_		)
															a__				      =		str(hash(a_		)		)
															a__				      =		filename[: max_length - len(a_		) - 8] + """...""" + hashed_filename + """.lock"""
															return os.path.join(a_  ,  a_		)
											else:
															return path




class  __snake_case      (   SCREAMING_SNAKE_CASE):







							'''simple docstring'''






							def __init__(							self  ,  a_  ,  a_=-1  ,  a_=None		):
											from .file_utils import relative_to_absolute_path

											super().__init__(a_  ,  timeout=a_  ,  max_filename_length=a_		)
											a__				      =		"""\\\\?\\""" + relative_to_absolute_path(self.lock_file		)


							def _a      (							self		):
											a__				      =		os.O_RDWR | os.O_CREAT | os.O_TRUNC

											try:
															a__				      =		os.open(self._lock_file  ,  a_		)
											except OSError:
															pass
											else:
															try:
																			msvcrt.locking(a_  ,  msvcrt.LK_NBLCK  ,  1		)
															except OSError:
																			os.close(a_		)
															else:
																			a__				      =		fd
											return None







							def _a      (							self		):
											a__				      =		self._lock_file_fd
											a__				      =		None
											msvcrt.locking(a_  ,  msvcrt.LK_UNLCK  ,  1		)
											os.close(a_		)

											try:
															os.remove(self._lock_file		)
											# Probably another instance of the application
											# that acquired the file lock.
											except OSError:
															pass
											return None




class  __snake_case      (   SCREAMING_SNAKE_CASE):







							'''simple docstring'''






							def __init__(							self  ,  a_  ,  a_=-1  ,  a_=None		):
											a__				      =		os.statvfs(os.path.dirname(a_		)		).f_namemax
											super().__init__(a_  ,  timeout=a_  ,  max_filename_length=a_		)


							def _a      (							self		):
											a__				      =		os.O_RDWR | os.O_CREAT | os.O_TRUNC
											a__				      =		os.open(self._lock_file  ,  a_		)

											try:
															fcntl.flock(a_  ,  fcntl.LOCK_EX | fcntl.LOCK_NB		)
											except OSError:
															os.close(a_		)
											else:
															a__				      =		fd
											return None







							def _a      (							self		):
											# Do not remove the lockfile:
											#
											#   https://github.com/benediktschmitt/py-filelock/issues/31
											#   https://stackoverflow.com/questions/17708885/flock-removing-locked-file-without-race-condition
											a__				      =		self._lock_file_fd
											a__				      =		None
											fcntl.flock(a_  ,  fcntl.LOCK_UN		)
											os.close(a_		)
											return None




class  __snake_case      (   SCREAMING_SNAKE_CASE):







							'''simple docstring'''






							def _a      (							self		):
											a__				      =		os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_TRUNC
											try:
															a__				      =		os.open(self._lock_file  ,  a_		)
											except OSError:
															pass
											else:
															a__				      =		fd
											return None







							def _a      (							self		):
											os.close(self._lock_file_fd		)
											a__				      =		None

											try:
															os.remove(self._lock_file		)
											# The file is already deleted and that's what we want.
											except OSError:
															pass
											return None




UpperCAmelCase							 =					None

if msvcrt:
	UpperCAmelCase							 =					WindowsFileLock
elif fcntl:
	UpperCAmelCase							 =					UnixFileLock
else:
	UpperCAmelCase							 =					SoftFileLock

	if warnings is not None:
		warnings.warn("""only soft file lock is available""")






def 			A_      (	__a     :				str = "The quick brown fox jumps over the lazy dog" ,		):

				"""simple docstring"""
				a__				      =		set()

				# Replace all the whitespace in our sentence
				a__				      =		input_str.replace(""" """ ,		""""""		)
				for alpha in input_str:
								if "a" <= alpha.lower() <= "z":
												frequency.add(alpha.lower()		)
				return len(__a		) == 26

def 			A_      (	__a     :				str = "The quick brown fox jumps over the lazy dog" ,		):

				"""simple docstring"""
				a__				      =		[False] * 26
				for char in input_str:
								if char.islower():
												a__				      =		True
								elif char.isupper():
												a__				      =		True
				return all(__a		)

def 			A_      (	__a     :				str = "The quick brown fox jumps over the lazy dog" ,		):

				"""simple docstring"""
				return len({char for char in input_str.lower() if char.isalpha()}		) == 26

def 			A_      (	):

				"""simple docstring"""
				from timeit import timeit

				a__				      =		"""from __main__ import is_pangram, is_pangram_faster, is_pangram_fastest"""
				print(timeit("""is_pangram()""" ,		setup=__a		)		)
				print(timeit("""is_pangram_faster()""" ,		setup=__a		)		)
				print(timeit("""is_pangram_fastest()""" ,		setup=__a		)		)
				# 5.348480500048026, 2.6477354579837993, 1.8470395830227062
				# 5.036091582966037, 2.644472333951853,  1.8869528750656173


if __name__ == "__main__":
	import doctest

	doctest.testmod()
	benchmark()

