@ -737,8 +737,8 @@ def extract_basic_auth(url):
parts . hostname if parts . port is None
parts . hostname if parts . port is None
else ' %s : %d ' % ( parts . hostname , parts . port ) ) ) )
else ' %s : %d ' % ( parts . hostname , parts . port ) ) ) )
auth_payload = base64 . b64encode (
auth_payload = base64 . b64encode (
( ' %s : %s ' % ( parts . username , parts . password or ' ' ) ) . encode ( ' utf-8 ' ) )
( ' %s : %s ' % ( parts . username , parts . password or ' ' ) ) . encode ( ) )
return url , ' Basic ' + auth_payload . decode ( ' utf-8 ' )
return url , f' Basic { auth_payload . decode ( ) } '
def sanitized_Request ( url , * args , * * kwargs ) :
def sanitized_Request ( url , * args , * * kwargs ) :
@ -1339,7 +1339,7 @@ class YoutubeDLHandler(compat_urllib_request.HTTPHandler):
location = resp . headers . get ( ' Location ' )
location = resp . headers . get ( ' Location ' )
if location :
if location :
# As of RFC 2616 default charset is iso-8859-1 that is respected by python 3
# As of RFC 2616 default charset is iso-8859-1 that is respected by python 3
location = location . encode ( ' iso-8859-1 ' ) . decode ( ' utf-8 ' )
location = location . encode ( ' iso-8859-1 ' ) . decode ( )
location_escaped = escape_url ( location )
location_escaped = escape_url ( location )
if location != location_escaped :
if location != location_escaped :
del resp . headers [ ' Location ' ]
del resp . headers [ ' Location ' ]
@ -2309,7 +2309,7 @@ def setproctitle(title):
# a bytestring, but since unicode_literals turns
# a bytestring, but since unicode_literals turns
# every string into a unicode string, it fails.
# every string into a unicode string, it fails.
return
return
title_bytes = title . encode ( ' utf-8 ' )
title_bytes = title . encode ( )
buf = ctypes . create_string_buffer ( len ( title_bytes ) )
buf = ctypes . create_string_buffer ( len ( title_bytes ) )
buf . value = title_bytes
buf . value = title_bytes
try :
try :
@ -2351,13 +2351,13 @@ def base_url(url):
def urljoin ( base , path ) :
def urljoin ( base , path ) :
if isinstance ( path , bytes ) :
if isinstance ( path , bytes ) :
path = path . decode ( ' utf-8 ' )
path = path . decode ( )
if not isinstance ( path , compat_str ) or not path :
if not isinstance ( path , compat_str ) or not path :
return None
return None
if re . match ( r ' ^(?:[a-zA-Z][a-zA-Z0-9+-.]*:)?// ' , path ) :
if re . match ( r ' ^(?:[a-zA-Z][a-zA-Z0-9+-.]*:)?// ' , path ) :
return path
return path
if isinstance ( base , bytes ) :
if isinstance ( base , bytes ) :
base = base . decode ( ' utf-8 ' )
base = base . decode ( )
if not isinstance ( base , compat_str ) or not re . match (
if not isinstance ( base , compat_str ) or not re . match (
r ' ^(?:https?:)?// ' , base ) :
r ' ^(?:https?:)?// ' , base ) :
return None
return None
@ -2557,49 +2557,48 @@ def get_exe_version(exe, args=['--version'],
class LazyList ( collections . abc . Sequence ) :
class LazyList ( collections . abc . Sequence ) :
''' Lazy immutable list from an iterable
""" Lazy immutable list from an iterable
Note that slices of a LazyList are lists and not LazyList '''
Note that slices of a LazyList are lists and not LazyList """
class IndexError ( IndexError ) :
class IndexError ( IndexError ) :
pass
pass
def __init__ ( self , iterable , * , reverse = False , _cache = None ) :
def __init__ ( self , iterable , * , reverse = False , _cache = None ) :
self . _ _ iterable = iter ( iterable )
self . _ iterable = iter ( iterable )
self . _ _ cache = [ ] if _cache is None else _cache
self . _ cache = [ ] if _cache is None else _cache
self . _ _ reversed = reverse
self . _ reversed = reverse
def __iter__ ( self ) :
def __iter__ ( self ) :
if self . _ _ reversed:
if self . _ reversed:
# We need to consume the entire iterable to iterate in reverse
# We need to consume the entire iterable to iterate in reverse
yield from self . exhaust ( )
yield from self . exhaust ( )
return
return
yield from self . _ _ cache
yield from self . _ cache
for item in self . _ _ iterable:
for item in self . _ iterable:
self . _ _ cache. append ( item )
self . _ cache. append ( item )
yield item
yield item
def __exhaust ( self ) :
def _exhaust ( self ) :
self . __cache . extend ( self . __iterable )
self . _cache . extend ( self . _iterable )
# Discard the emptied iterable to make it pickle-able
self . _iterable = [ ] # Discard the emptied iterable to make it pickle-able
self . __iterable = [ ]
return self . _cache
return self . __cache
def exhaust ( self ) :
def exhaust ( self ) :
''' Evaluate the entire iterable '''
""" Evaluate the entire iterable """
return self . _ _ exhaust( ) [ : : - 1 if self . _ _reversed else 1 ]
return self . _ exhaust( ) [ : : - 1 if self . _reversed else 1 ]
@staticmethod
@staticmethod
def _ _ reverse_index( x ) :
def _ reverse_index( x ) :
return None if x is None else - ( x + 1 )
return None if x is None else - ( x + 1 )
def __getitem__ ( self , idx ) :
def __getitem__ ( self , idx ) :
if isinstance ( idx , slice ) :
if isinstance ( idx , slice ) :
if self . _ _ reversed:
if self . _ reversed:
idx = slice ( self . _ _ reverse_index( idx . start ) , self . _ _reverse_index( idx . stop ) , - ( idx . step or 1 ) )
idx = slice ( self . _ reverse_index( idx . start ) , self . _reverse_index( idx . stop ) , - ( idx . step or 1 ) )
start , stop , step = idx . start , idx . stop , idx . step or 1
start , stop , step = idx . start , idx . stop , idx . step or 1
elif isinstance ( idx , int ) :
elif isinstance ( idx , int ) :
if self . _ _ reversed:
if self . _ reversed:
idx = self . _ _ reverse_index( idx )
idx = self . _ reverse_index( idx )
start , stop , step = idx , idx , 0
start , stop , step = idx , idx , 0
else :
else :
raise TypeError ( ' indices must be integers or slices ' )
raise TypeError ( ' indices must be integers or slices ' )
@ -2608,35 +2607,35 @@ class LazyList(collections.abc.Sequence):
or ( stop is None and step > 0 ) ) :
or ( stop is None and step > 0 ) ) :
# We need to consume the entire iterable to be able to slice from the end
# We need to consume the entire iterable to be able to slice from the end
# Obviously, never use this with infinite iterables
# Obviously, never use this with infinite iterables
self . _ _ exhaust( )
self . _ exhaust( )
try :
try :
return self . _ _ cache[ idx ]
return self . _ cache[ idx ]
except IndexError as e :
except IndexError as e :
raise self . IndexError ( e ) from e
raise self . IndexError ( e ) from e
n = max ( start or 0 , stop or 0 ) - len ( self . _ _ cache) + 1
n = max ( start or 0 , stop or 0 ) - len ( self . _ cache) + 1
if n > 0 :
if n > 0 :
self . _ _ cache. extend ( itertools . islice ( self . _ _iterable, n ) )
self . _ cache. extend ( itertools . islice ( self . _iterable, n ) )
try :
try :
return self . _ _ cache[ idx ]
return self . _ cache[ idx ]
except IndexError as e :
except IndexError as e :
raise self . IndexError ( e ) from e
raise self . IndexError ( e ) from e
def __bool__ ( self ) :
def __bool__ ( self ) :
try :
try :
self [ - 1 ] if self . _ _ reversed else self [ 0 ]
self [ - 1 ] if self . _ reversed else self [ 0 ]
except self . IndexError :
except self . IndexError :
return False
return False
return True
return True
def __len__ ( self ) :
def __len__ ( self ) :
self . _ _ exhaust( )
self . _ exhaust( )
return len ( self . _ _ cache)
return len ( self . _ cache)
def __reversed__ ( self ) :
def __reversed__ ( self ) :
return type ( self ) ( self . _ _ iterable, reverse = not self . _ _ reversed, _cache = self . _ _cache)
return type ( self ) ( self . _ iterable, reverse = not self . _ reversed, _cache = self . _cache)
def __copy__ ( self ) :
def __copy__ ( self ) :
return type ( self ) ( self . _ _ iterable, reverse = self . _ _reversed, _cache = self . _ _cache)
return type ( self ) ( self . _ iterable, reverse = self . _reversed, _cache = self . _cache)
def __repr__ ( self ) :
def __repr__ ( self ) :
# repr and str should mimic a list. So we exhaust the iterable
# repr and str should mimic a list. So we exhaust the iterable
@ -2850,9 +2849,9 @@ def _multipart_encode_impl(data, boundary):
for k , v in data . items ( ) :
for k , v in data . items ( ) :
out + = b ' -- ' + boundary . encode ( ' ascii ' ) + b ' \r \n '
out + = b ' -- ' + boundary . encode ( ' ascii ' ) + b ' \r \n '
if isinstance ( k , compat_str ) :
if isinstance ( k , compat_str ) :
k = k . encode ( ' utf-8 ' )
k = k . encode ( )
if isinstance ( v , compat_str ) :
if isinstance ( v , compat_str ) :
v = v . encode ( ' utf-8 ' )
v = v . encode ( )
# RFC 2047 requires non-ASCII field names to be encoded, while RFC 7578
# RFC 2047 requires non-ASCII field names to be encoded, while RFC 7578
# suggests sending UTF-8 directly. Firefox sends UTF-8, too
# suggests sending UTF-8 directly. Firefox sends UTF-8, too
content = b ' Content-Disposition: form-data; name= " ' + k + b ' " \r \n \r \n ' + v + b ' \r \n '
content = b ' Content-Disposition: form-data; name= " ' + k + b ' " \r \n \r \n ' + v + b ' \r \n '
@ -4741,7 +4740,7 @@ def write_xattr(path, key, value):
' Couldn \' t find a tool to set the xattrs. Install either the python " xattr " or " pyxattr " modules or the '
' Couldn \' t find a tool to set the xattrs. Install either the python " xattr " or " pyxattr " modules or the '
+ ( ' " xattr " binary ' if sys . platform != ' linux ' else ' GNU " attr " package (which contains the " setfattr " tool) ' ) )
+ ( ' " xattr " binary ' if sys . platform != ' linux ' else ' GNU " attr " package (which contains the " setfattr " tool) ' ) )
value = value . decode ( ' utf-8 ' )
value = value . decode ( )
try :
try :
p = Popen (
p = Popen (
[ exe , ' -w ' , key , value , path ] if exe == ' xattr ' else [ exe , ' -n ' , key , ' -v ' , value , path ] ,
[ exe , ' -w ' , key , value , path ] if exe == ' xattr ' else [ exe , ' -n ' , key , ' -v ' , value , path ] ,
@ -4820,7 +4819,7 @@ def iri_to_uri(iri):
net_location + = ' : ' + urllib . parse . quote ( iri_parts . password , safe = r " !$ % & ' ()*+,~ " )
net_location + = ' : ' + urllib . parse . quote ( iri_parts . password , safe = r " !$ % & ' ()*+,~ " )
net_location + = ' @ '
net_location + = ' @ '
net_location + = iri_parts . hostname . encode ( ' idna ' ) . decode ( ' utf-8 ' ) # Punycode for Unicode hostnames.
net_location + = iri_parts . hostname . encode ( ' idna ' ) . decode ( ) # Punycode for Unicode hostnames.
# The 'idna' encoding produces ASCII text.
# The 'idna' encoding produces ASCII text.
if iri_parts . port is not None and iri_parts . port != 80 :
if iri_parts . port is not None and iri_parts . port != 80 :
net_location + = ' : ' + str ( iri_parts . port )
net_location + = ' : ' + str ( iri_parts . port )
@ -5063,9 +5062,9 @@ def jwt_encode_hs256(payload_data, key, headers={}):
}
}
if headers :
if headers :
header_data . update ( headers )
header_data . update ( headers )
header_b64 = base64 . b64encode ( json . dumps ( header_data ) . encode ( ' utf-8 ' ) )
header_b64 = base64 . b64encode ( json . dumps ( header_data ) . encode ( ) )
payload_b64 = base64 . b64encode ( json . dumps ( payload_data ) . encode ( ' utf-8 ' ) )
payload_b64 = base64 . b64encode ( json . dumps ( payload_data ) . encode ( ) )
h = hmac . new ( key . encode ( ' utf-8 ' ) , header_b64 + b ' . ' + payload_b64 , hashlib . sha256 )
h = hmac . new ( key . encode ( ) , header_b64 + b ' . ' + payload_b64 , hashlib . sha256 )
signature_b64 = base64 . b64encode ( h . digest ( ) )
signature_b64 = base64 . b64encode ( h . digest ( ) )
token = header_b64 + b ' . ' + payload_b64 + b ' . ' + signature_b64
token = header_b64 + b ' . ' + payload_b64 + b ' . ' + signature_b64
return token
return token