[Python-Dev] readd u'' literal support in 3.3?
Vinay Sajip
vinay_sajip at yahoo.co.uk
Tue Dec 13 16:54:21 CET 2011
Laurence Rowe <l <at> lrowe.co.uk> writes:
> The approach that most people seem to have settled on for porting
> libraries to Python 3 is to make a single codebase that is compatible with
> both Python 2 and Python 3, perhaps making use of the six library. If I
> understand correctly, Chris' experience of porting WebOb was that there is
> a large amount of manual work required in this approach in part because of
> the many u'' strings in libraries that extensively use unicode. It should
> be possible to automate this with the same approach as 2to3, but instead
> of a transform from 2->3 it would transform code from 2->(2 & 3). In this
> case the transform would only have to be run once (rather than on every
> setup.py install) and would avoid the difficulties of debugging with
> tracebacks that do not exactly match the source code.
I started writing a tool today, tentatively called '2to23', which aims to do
this. It's basically 2to3, but with a package of custom fixers in a package
'lib2to23.fixers' adapted from the corresponding fixers in lib2to3. It's
experimental work in progress at the moment. With a sample file like
import anything
import dummy
class CustomException(Exception):
pass
def func1():
a = u'abc'
b = b'def'
c = 'unchanged'
c1 = u'abc' u'def'
def func2():
try:
d = 5L
e = (int, long)
f = (long, int)
g = func3()
if isinstance(g, basestring):
print 'a string'
elif isinstance(g, bytes):
print 'some bytes'
elif isinstance(g, unicode):
print 'a unicode string'
else:
print
for i in xrange(3):
pass
except Exception:
e = sys.exc_info()
raise CustomException, e[1], e[2]
class BaseClass:
pass
class OtherBaseClass:
pass
class MetaClass:
pass
class DerivedClass(BaseClass, OtherBaseClass):
__metaclass__ = MetaClass
2to23 gives the following suggested changes:
--- sample.py (original)
+++ sample.py (refactored)
@@ -1,34 +1,41 @@
import anything
import dummy
+from django.utils.py3 import long_type
+from django.utils.py3 import string_types
+from django.utils.py3 import binary_type
+from django.utils.py3 import b
+from django.utils.py3 import text_type
+from django.utils.py3 import u
+from django.utils.py3 import xrange
class CustomException(Exception):
pass
def func1():
- a = u'abc'
- b = b'def'
+ a = u('abc')
+ b = b('def')
c = 'unchanged'
- c1 = u'abc' u'def'
+ c1 = u('abc') u('def')
def func2():
try:
- d = 5L
+ d = long_type(5)
e = (int, long)
f = (long, int)
g = func3()
- if isinstance(g, basestring):
- print 'a string'
- elif isinstance(g, bytes):
- print 'some bytes'
- elif isinstance(g, unicode):
- print 'a unicode string'
+ if isinstance(g, string_types):
+ print('a string')
+ elif isinstance(g, binary_type):
+ print('some bytes')
+ elif isinstance(g, text_type):
+ print('a unicode string')
else:
- print
+ print()
for i in xrange(3):
pass
except Exception:
e = sys.exc_info()
- raise CustomException, e[1], e[2]
+ raise CustomException(e[1]).with_traceback(e[2])
class BaseClass:
pass
@@ -39,8 +46,8 @@
class MetaClass:
pass
-class DerivedClass(BaseClass, OtherBaseClass):
- __metaclass__ = MetaClass
+class DerivedClass(with_metaclass(MetaClass, BaseClass, OtherBaseClass)):
+ pass
As you can see, there's still a bit of work to do, and the sample doesn't cover
all use cases yet. I'll be cross-checking it using my recent Django porting work
to confirm that it covers everything at least needed for that port, which is why
the fixers currently generate imports from django.utils.py3. Obviously, I'll
change this in due course.
Regards,
Vinay Sajip
More information about the Python-Dev
mailing list