On Saturday, June 2, 2012 2:20:50 PM UTC-4, Tomas Schertel wrote:
>
> I saw a few posts talking about web.py run with python 3 and noticed one 
> that said there's no reason in porting web.py to python 3 if wsgi layers 
> still runs with python 2.
> Why don't make web.py able to run on both python, 2.X and 3.x?
> Bottle and Cherrypy does that.
> Flup already has a branch for python 3.
>

I'm not sure if the developers have any sort of Python 
3 comparability roadmap (I didn't see anything on the issue tracker, and 
only this note https://bugs.launchpad.net/webpy/+bug/277266 from 2008) but 
I agree, I think it should be possible to enable web.py to support both.

I just discovered web.py in the last week, and I'm totally hooked!  It's 
exactly what I imagined wanting out of a Python web-framework.  I have a 
Python project I've been working on, that I'd love to have hook into 
web.py, but it's Python 3 :(  So I spent a few hours today trying to figure 
out what needed to be done to get it working, and it doesn't seem all that 
bad.

1. Pull in CherryPy's updated web server code, which is now 2/3 compatible.
2. Run python -3:
      I ran this on a small test setup and saw the following:

$ python -3 code.py
http://0.0.0.0:8080/
/usr/lib/python2.6/site-packages/web/template.py:925: DeprecationWarning: 
the compiler package has been removed in Python 3.0
  import compiler
/usr/lib/python2.6/site-packages/markdown/blockprocessors.py:163: 
DeprecationWarning: classic int division
  indent_level = len(m.group(1))/markdown.TAB_LENGTH
127.0.0.1:57576 - - [22/Jul/2012 01:03:37] "HTTP/1.1 GET /Welcome" - 200 OK
127.0.0.1:57576 - - [22/Jul/2012 01:03:38] "HTTP/1.1 GET /" - 200 OK

    This seems pretty promising to me.  I think the compiler error can be 
resolved by switching to http://docs.python.org/library/ast.html#ast.parse but 
even if it's more complicated than that, the import is in a try block, and 
fails reasonably gracefully.  It looks like Jython supports AST as well, 
which would make this an even better switch: 
http://www.jython.org/docs/library/ast.html .  The markdown error is of no 
concern, since Python Markdown has a 3.0 compatible version available: 
http://freewisdom.org/projects/python-markdown/News
3. Run 2to3:
    2to3 runs successfully, and by and large cleans things up well.  It 
runs into a fair bit of trouble with web.py's unicode handling, such as 
utils.safestr and utils.safeunicode, generating this diff of safestr:

@@ -364,12 +364,12 @@
         >>> safestr(2)
         '2'
     """
-    if isinstance(obj, unicode):
+    if isinstance(obj, str):
         return obj.encode(encoding)
     elif isinstance(obj, str):
         return obj
     elif hasattr(obj, 'next'): # iterator
-        return itertools.imap(safestr, obj)
+        return map(safestr, obj)
     else:
         return str(obj)

    You'll notice that it replaces unicode with str, breaking the method's 
expected behavior.  I'm not sure if it makes more sense to define a custom 
2to3 fixer, or figure out a better way to define / compartmentalize this 
code, but this will need to be cleaned up.
4. Fix runtime exceptions:
    Running 2to3 isn't enough to kick of the server though, I got a handful 
of stack traces that I was able to correct with the following patch:

Series of fixes to resolve stack traces in 3.2.

Fixed bad reference to __builtin__: 
http://pydev.blogspot.com/2008/11/making-code-work-in-python-2-and-3.html #5
Changed UserDict.DictMixin to collections.MutableMapping per 
http://bugs.python.org/issue2876 but this may not be enough: 
http://bugs.python.org/issue7975
Removed 'object' parent from TemplateResult: 
http://stackoverflow.com/questions/3003053/metaclass-multiple-inheritance-inconsistency
Removed 'exceptions' import
---- Enough to start the server
Removed str decode('UTF-8') call

diff -r 1b5bb3b5399b -r c823902ee50f application.py
--- a/application.py Sat Jul 21 23:27:20 2012 -0400
+++ b/application.py Sat Jul 21 23:37:09 2012 -0400
@@ -15,7 +15,6 @@
 import itertools
 import os
 import types
-from exceptions import SystemExit
 
 try:
     import wsgiref.handlers
@@ -374,12 +373,6 @@
 
         ctx.fullpath = ctx.path + ctx.query
         
-        for k, v in ctx.items():
-            # convert all string values to unicode values and replace 
-            # malformed data with a suitable replacement marker.
-            if isinstance(v, str):
-                ctx[k] = v.decode('utf-8', 'replace') 
-
         # status must always be str
         ctx.status = '200 OK'
         
diff -r 1b5bb3b5399b -r c823902ee50f template.py
--- a/template.py Sat Jul 21 23:27:20 2012 -0400
+++ b/template.py Sat Jul 21 23:37:09 2012 -0400
@@ -40,7 +40,7 @@
 import sys
 import glob
 import re
-from UserDict import DictMixin
+from collections import MutableMapping
 import warnings
 
 from .utils import storage, safeunicode, safestr, re_compile
@@ -721,8 +721,8 @@
     "__import__", # some c-libraries like datetime requires __import__ to 
present in the namespace
 ]
 
-import builtins
-TEMPLATE_BUILTINS = dict([(name, getattr(__builtin__, name)) for name in 
TEMPLATE_BUILTIN_NAMES if name in builtins.__dict__])
+import builtins as __builtin__
+TEMPLATE_BUILTINS = dict([(name, getattr(__builtin__, name)) for name in 
TEMPLATE_BUILTIN_NAMES if name in __builtin__.__dict__])
 
 class ForLoop:
     """
@@ -1209,7 +1209,7 @@
         e = SecurityError("%s:%d - execution of '%s' statements is denied" 
% (self.filename, lineno, nodename))
         self.errors.append(e)
 
-class TemplateResult(object, DictMixin):
+class TemplateResult(MutableMapping):
     """Dictionary like object for storing template output.
     
     The result of a template execution is usally a string, but sometimes it
diff -r 1b5bb3b5399b -r c823902ee50f utils.py
--- a/utils.py Sat Jul 21 23:27:20 2012 -0400
+++ b/utils.py Sat Jul 21 23:37:09 2012 -0400
@@ -259,7 +259,7 @@
 counter = Counter
 
 iters = [list, tuple]
-import builtins
+import builtins as __builtin__
 if hasattr(__builtin__, 'set'):
     iters.append(set)
 if hasattr(__builtin__, 'frozenset'):


    This was enough to start a server, but there are likely more robust 
ways of solving these exceptions.
5. Update test suite
    I saw 4 failures running the test suite locally on Python 2.7, and 41 
failures and 12 errors on 3.2.  Most of these were just encoding issues, 
like:

File ".\web\utils.py", line 337, in web.utils.safeunicode
Failed example:
    safeunicode('hello')
Expected:
    u'hello'
Got:
    'hello' 

    But the tests will need to be updated and expanded to ensure no 
regressions.


Needless to say, it looks to me like there's still work to be done, but 
it's not impossible.  To the maintainers, do you have any plans to move 
towards Python 3?  I would be happy to help make this possible.

Michael

-- 
You received this message because you are subscribed to the Google Groups 
"web.py" group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/webpy/-/WeOvy-V51sgJ.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/webpy?hl=en.

Reply via email to