1- """Utilities for writing code that runs on Python 2 and 3"""
2-
3- # Copyright (c) 2010-2015 Benjamin Peterson
1+ # Copyright (c) 2010-2020 Benjamin Peterson
42#
53# Permission is hereby granted, free of charge, to any person obtaining a copy
64# of this software and associated documentation files (the "Software"), to deal
2018# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2119# SOFTWARE.
2220
21+ """Utilities for writing code that runs on Python 2 and 3"""
22+
2323from __future__ import absolute_import
2424
2525import functools
2929import types
3030
3131__author__ = "Benjamin Peterson <benjamin@python.org>"
32- __version__ = "1.10 .0"
32+ __version__ = "1.16 .0"
3333
3434
3535# Useful for very coarse version differentiation.
@@ -71,6 +71,11 @@ def __len__(self):
7171 MAXSIZE = int ((1 << 63 ) - 1 )
7272 del X
7373
74+ if PY34 :
75+ from importlib .util import spec_from_loader
76+ else :
77+ spec_from_loader = None
78+
7479
7580def _add_doc (func , doc ):
7681 """Add documentation to a function."""
@@ -186,6 +191,11 @@ def find_module(self, fullname, path=None):
186191 return self
187192 return None
188193
194+ def find_spec (self , fullname , path , target = None ):
195+ if fullname in self .known_modules :
196+ return spec_from_loader (fullname , self )
197+ return None
198+
189199 def __get_module (self , fullname ):
190200 try :
191201 return self .known_modules [fullname ]
@@ -223,6 +233,12 @@ def get_code(self, fullname):
223233 return None
224234 get_source = get_code # same as get_code
225235
236+ def create_module (self , spec ):
237+ return self .load_module (spec .name )
238+
239+ def exec_module (self , module ):
240+ pass
241+
226242_importer = _SixMetaPathImporter (__name__ )
227243
228244
@@ -241,6 +257,7 @@ class _MovedItems(_LazyModule):
241257 MovedAttribute ("map" , "itertools" , "builtins" , "imap" , "map" ),
242258 MovedAttribute ("getcwd" , "os" , "os" , "getcwdu" , "getcwd" ),
243259 MovedAttribute ("getcwdb" , "os" , "os" , "getcwd" , "getcwdb" ),
260+ MovedAttribute ("getoutput" , "commands" , "subprocess" ),
244261 MovedAttribute ("range" , "__builtin__" , "builtins" , "xrange" , "range" ),
245262 MovedAttribute ("reload_module" , "__builtin__" , "importlib" if PY34 else "imp" , "reload" ),
246263 MovedAttribute ("reduce" , "__builtin__" , "functools" ),
@@ -254,18 +271,21 @@ class _MovedItems(_LazyModule):
254271 MovedAttribute ("zip_longest" , "itertools" , "itertools" , "izip_longest" , "zip_longest" ),
255272 MovedModule ("builtins" , "__builtin__" ),
256273 MovedModule ("configparser" , "ConfigParser" ),
274+ MovedModule ("collections_abc" , "collections" , "collections.abc" if sys .version_info >= (3 , 3 ) else "collections" ),
257275 MovedModule ("copyreg" , "copy_reg" ),
258276 MovedModule ("dbm_gnu" , "gdbm" , "dbm.gnu" ),
259- MovedModule ("_dummy_thread" , "dummy_thread" , "_dummy_thread" ),
277+ MovedModule ("dbm_ndbm" , "dbm" , "dbm.ndbm" ),
278+ MovedModule ("_dummy_thread" , "dummy_thread" , "_dummy_thread" if sys .version_info < (3 , 9 ) else "_thread" ),
260279 MovedModule ("http_cookiejar" , "cookielib" , "http.cookiejar" ),
261280 MovedModule ("http_cookies" , "Cookie" , "http.cookies" ),
262281 MovedModule ("html_entities" , "htmlentitydefs" , "html.entities" ),
263282 MovedModule ("html_parser" , "HTMLParser" , "html.parser" ),
264283 MovedModule ("http_client" , "httplib" , "http.client" ),
284+ MovedModule ("email_mime_base" , "email.MIMEBase" , "email.mime.base" ),
285+ MovedModule ("email_mime_image" , "email.MIMEImage" , "email.mime.image" ),
265286 MovedModule ("email_mime_multipart" , "email.MIMEMultipart" , "email.mime.multipart" ),
266287 MovedModule ("email_mime_nonmultipart" , "email.MIMENonMultipart" , "email.mime.nonmultipart" ),
267288 MovedModule ("email_mime_text" , "email.MIMEText" , "email.mime.text" ),
268- MovedModule ("email_mime_base" , "email.MIMEBase" , "email.mime.base" ),
269289 MovedModule ("BaseHTTPServer" , "BaseHTTPServer" , "http.server" ),
270290 MovedModule ("CGIHTTPServer" , "CGIHTTPServer" , "http.server" ),
271291 MovedModule ("SimpleHTTPServer" , "SimpleHTTPServer" , "http.server" ),
@@ -337,10 +357,12 @@ class Module_six_moves_urllib_parse(_LazyModule):
337357 MovedAttribute ("quote_plus" , "urllib" , "urllib.parse" ),
338358 MovedAttribute ("unquote" , "urllib" , "urllib.parse" ),
339359 MovedAttribute ("unquote_plus" , "urllib" , "urllib.parse" ),
360+ MovedAttribute ("unquote_to_bytes" , "urllib" , "urllib.parse" , "unquote" , "unquote_to_bytes" ),
340361 MovedAttribute ("urlencode" , "urllib" , "urllib.parse" ),
341362 MovedAttribute ("splitquery" , "urllib" , "urllib.parse" ),
342363 MovedAttribute ("splittag" , "urllib" , "urllib.parse" ),
343364 MovedAttribute ("splituser" , "urllib" , "urllib.parse" ),
365+ MovedAttribute ("splitvalue" , "urllib" , "urllib.parse" ),
344366 MovedAttribute ("uses_fragment" , "urlparse" , "urllib.parse" ),
345367 MovedAttribute ("uses_netloc" , "urlparse" , "urllib.parse" ),
346368 MovedAttribute ("uses_params" , "urlparse" , "urllib.parse" ),
@@ -416,6 +438,8 @@ class Module_six_moves_urllib_request(_LazyModule):
416438 MovedAttribute ("URLopener" , "urllib" , "urllib.request" ),
417439 MovedAttribute ("FancyURLopener" , "urllib" , "urllib.request" ),
418440 MovedAttribute ("proxy_bypass" , "urllib" , "urllib.request" ),
441+ MovedAttribute ("parse_http_list" , "urllib2" , "urllib.request" ),
442+ MovedAttribute ("parse_keqv_list" , "urllib2" , "urllib.request" ),
419443]
420444for attr in _urllib_request_moved_attributes :
421445 setattr (Module_six_moves_urllib_request , attr .name , attr )
@@ -631,13 +655,16 @@ def u(s):
631655 import io
632656 StringIO = io .StringIO
633657 BytesIO = io .BytesIO
658+ del io
634659 _assertCountEqual = "assertCountEqual"
635660 if sys .version_info [1 ] <= 1 :
636661 _assertRaisesRegex = "assertRaisesRegexp"
637662 _assertRegex = "assertRegexpMatches"
663+ _assertNotRegex = "assertNotRegexpMatches"
638664 else :
639665 _assertRaisesRegex = "assertRaisesRegex"
640666 _assertRegex = "assertRegex"
667+ _assertNotRegex = "assertNotRegex"
641668else :
642669 def b (s ):
643670 return s
@@ -659,6 +686,7 @@ def indexbytes(buf, i):
659686 _assertCountEqual = "assertItemsEqual"
660687 _assertRaisesRegex = "assertRaisesRegexp"
661688 _assertRegex = "assertRegexpMatches"
689+ _assertNotRegex = "assertNotRegexpMatches"
662690_add_doc (b , """Byte literal""" )
663691_add_doc (u , """Text literal""" )
664692
@@ -675,15 +703,23 @@ def assertRegex(self, *args, **kwargs):
675703 return getattr (self , _assertRegex )(* args , ** kwargs )
676704
677705
706+ def assertNotRegex (self , * args , ** kwargs ):
707+ return getattr (self , _assertNotRegex )(* args , ** kwargs )
708+
709+
678710if PY3 :
679711 exec_ = getattr (moves .builtins , "exec" )
680712
681713 def reraise (tp , value , tb = None ):
682- if value is None :
683- value = tp ()
684- if value .__traceback__ is not tb :
685- raise value .with_traceback (tb )
686- raise value
714+ try :
715+ if value is None :
716+ value = tp ()
717+ if value .__traceback__ is not tb :
718+ raise value .with_traceback (tb )
719+ raise value
720+ finally :
721+ value = None
722+ tb = None
687723
688724else :
689725 def exec_ (_code_ , _globs_ = None , _locs_ = None ):
@@ -699,19 +735,19 @@ def exec_(_code_, _globs_=None, _locs_=None):
699735 exec ("""exec _code_ in _globs_, _locs_""" )
700736
701737 exec_ ("""def reraise(tp, value, tb=None):
702- raise tp, value, tb
738+ try:
739+ raise tp, value, tb
740+ finally:
741+ tb = None
703742""" )
704743
705744
706- if sys .version_info [:2 ] == (3 , 2 ):
745+ if sys .version_info [:2 ] > (3 ,):
707746 exec_ ("""def raise_from(value, from_value):
708- if from_value is None:
709- raise value
710- raise value from from_value
711- """ )
712- elif sys .version_info [:2 ] > (3 , 2 ):
713- exec_ ("""def raise_from(value, from_value):
714- raise value from from_value
747+ try:
748+ raise value from from_value
749+ finally:
750+ value = None
715751""" )
716752else :
717753 def raise_from (value , from_value ):
@@ -786,13 +822,33 @@ def print_(*args, **kwargs):
786822_add_doc (reraise , """Reraise an exception.""" )
787823
788824if sys .version_info [0 :2 ] < (3 , 4 ):
825+ # This does exactly the same what the :func:`py3:functools.update_wrapper`
826+ # function does on Python versions after 3.2. It sets the ``__wrapped__``
827+ # attribute on ``wrapper`` object and it doesn't raise an error if any of
828+ # the attributes mentioned in ``assigned`` and ``updated`` are missing on
829+ # ``wrapped`` object.
830+ def _update_wrapper (wrapper , wrapped ,
831+ assigned = functools .WRAPPER_ASSIGNMENTS ,
832+ updated = functools .WRAPPER_UPDATES ):
833+ for attr in assigned :
834+ try :
835+ value = getattr (wrapped , attr )
836+ except AttributeError :
837+ continue
838+ else :
839+ setattr (wrapper , attr , value )
840+ for attr in updated :
841+ getattr (wrapper , attr ).update (getattr (wrapped , attr , {}))
842+ wrapper .__wrapped__ = wrapped
843+ return wrapper
844+ _update_wrapper .__doc__ = functools .update_wrapper .__doc__
845+
789846 def wraps (wrapped , assigned = functools .WRAPPER_ASSIGNMENTS ,
790847 updated = functools .WRAPPER_UPDATES ):
791- def wrapper (f ):
792- f = functools .wraps (wrapped , assigned , updated )(f )
793- f .__wrapped__ = wrapped
794- return f
795- return wrapper
848+ return functools .partial (_update_wrapper , wrapped = wrapped ,
849+ assigned = assigned , updated = updated )
850+ wraps .__doc__ = functools .wraps .__doc__
851+
796852else :
797853 wraps = functools .wraps
798854
@@ -802,10 +858,22 @@ def with_metaclass(meta, *bases):
802858 # This requires a bit of explanation: the basic idea is to make a dummy
803859 # metaclass for one level of class instantiation that replaces itself with
804860 # the actual metaclass.
805- class metaclass (meta ):
861+ class metaclass (type ):
806862
807863 def __new__ (cls , name , this_bases , d ):
808- return meta (name , bases , d )
864+ if sys .version_info [:2 ] >= (3 , 7 ):
865+ # This version introduced PEP 560 that requires a bit
866+ # of extra care (we mimic what is done by __build_class__).
867+ resolved_bases = types .resolve_bases (bases )
868+ if resolved_bases is not bases :
869+ d ['__orig_bases__' ] = bases
870+ else :
871+ resolved_bases = bases
872+ return meta (name , resolved_bases , d )
873+
874+ @classmethod
875+ def __prepare__ (cls , name , this_bases ):
876+ return meta .__prepare__ (name , bases )
809877 return type .__new__ (metaclass , 'temporary_class' , (), {})
810878
811879
@@ -821,13 +889,75 @@ def wrapper(cls):
821889 orig_vars .pop (slots_var )
822890 orig_vars .pop ('__dict__' , None )
823891 orig_vars .pop ('__weakref__' , None )
892+ if hasattr (cls , '__qualname__' ):
893+ orig_vars ['__qualname__' ] = cls .__qualname__
824894 return metaclass (cls .__name__ , cls .__bases__ , orig_vars )
825895 return wrapper
826896
827897
898+ def ensure_binary (s , encoding = 'utf-8' , errors = 'strict' ):
899+ """Coerce **s** to six.binary_type.
900+
901+ For Python 2:
902+ - `unicode` -> encoded to `str`
903+ - `str` -> `str`
904+
905+ For Python 3:
906+ - `str` -> encoded to `bytes`
907+ - `bytes` -> `bytes`
908+ """
909+ if isinstance (s , binary_type ):
910+ return s
911+ if isinstance (s , text_type ):
912+ return s .encode (encoding , errors )
913+ raise TypeError ("not expecting type '%s'" % type (s ))
914+
915+
916+ def ensure_str (s , encoding = 'utf-8' , errors = 'strict' ):
917+ """Coerce *s* to `str`.
918+
919+ For Python 2:
920+ - `unicode` -> encoded to `str`
921+ - `str` -> `str`
922+
923+ For Python 3:
924+ - `str` -> `str`
925+ - `bytes` -> decoded to `str`
926+ """
927+ # Optimization: Fast return for the common case.
928+ if type (s ) is str :
929+ return s
930+ if PY2 and isinstance (s , text_type ):
931+ return s .encode (encoding , errors )
932+ elif PY3 and isinstance (s , binary_type ):
933+ return s .decode (encoding , errors )
934+ elif not isinstance (s , (text_type , binary_type )):
935+ raise TypeError ("not expecting type '%s'" % type (s ))
936+ return s
937+
938+
939+ def ensure_text (s , encoding = 'utf-8' , errors = 'strict' ):
940+ """Coerce *s* to six.text_type.
941+
942+ For Python 2:
943+ - `unicode` -> `unicode`
944+ - `str` -> `unicode`
945+
946+ For Python 3:
947+ - `str` -> `str`
948+ - `bytes` -> decoded to `str`
949+ """
950+ if isinstance (s , binary_type ):
951+ return s .decode (encoding , errors )
952+ elif isinstance (s , text_type ):
953+ return s
954+ else :
955+ raise TypeError ("not expecting type '%s'" % type (s ))
956+
957+
828958def python_2_unicode_compatible (klass ):
829959 """
830- A decorator that defines __unicode__ and __str__ methods under Python 2.
960+ A class decorator that defines __unicode__ and __str__ methods under Python 2.
831961 Under Python 3 it does nothing.
832962
833963 To support Python 2 and 3 with a single code base, define a __str__ method
0 commit comments