Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

py3 fixalltests #110

Draft
wants to merge 28 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
8303fe6
Raw 2to3 changes.
msdemlei Dec 26, 2017
a5a7dbb
Cleaning up some ugly 2to3 changes manually.
msdemlei Dec 26, 2017
618ae95
Raw 2to3 changes to auxiliary material.
msdemlei Dec 26, 2017
392a73d
Experimental move to zope.implementer.
msdemlei Dec 26, 2017
566cfb9
First version that can actually run some unit tests.
msdemlei Dec 30, 2017
f1a8b69
Fixing adapters and flatteners initially loaded for python3.
msdemlei Jan 13, 2018
d8b072d
Fixing for removal of reload() in python3.
msdemlei Jan 13, 2018
28e0b82
removing encodes that probably should no longer be there.
msdemlei Jan 13, 2018
a8241bf
Fixing use of func_code in getattrs.
msdemlei Jan 13, 2018
8bf1265
Adding a flattener for bytes (assuming they're utf-8-encoded)
msdemlei Jan 13, 2018
ee29c67
Replacing file with open
msdemlei Jan 13, 2018
29d811d
Replacing two leftover uses of string.split.
msdemlei Jan 13, 2018
80f0c40
Fixing entity creation
msdemlei Jan 13, 2018
31a1ee2
Replacing im_func with __func__ in getattr.
msdemlei Jan 13, 2018
8ab6de0
Fixing the traceback attribute in FlattnerErrors to retain python2 be…
msdemlei Jan 14, 2018
6a33c15
Making htmlstr and htmlfile aliases for xmlstr and htmlfile.
msdemlei Jan 14, 2018
74afc45
Minor fixes to tests to make test_rend pass.
msdemlei Jan 14, 2018
e872980
Updating i18n and its tests to make tests pass in python3.
msdemlei Jan 14, 2018
641eae8
The appserver now eventually writes bytes to the request.
msdemlei Jan 14, 2018
9d6539d
String/bytes separation for compress.py.
msdemlei Jan 14, 2018
1e87ce5
fixing disktemplate tests for string/bytes separation.
msdemlei Jan 14, 2018
fbc4f93
Porting guard hashes and a various other guard code to python3.
msdemlei Jan 14, 2018
5557e66
Fixing athena unit tests.
msdemlei Jan 21, 2018
2b37f64
Forcing testutil.FakeRequest.uri to be a byte string now
msdemlei Jan 21, 2018
e40aea3
Fixing athena.py for json.serialize->dumps renaming.
msdemlei Jan 21, 2018
83c253a
Updating tests (and a very few places in code) to actually implement
msdemlei Jan 21, 2018
230e640
first round of almost being there to have all tests pass with subunit…
wthie Oct 3, 2020
2ddb646
qx6minimal3 is up and running, need to look into loaders there are cu…
wthie Dec 29, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
build
dist
*dropin.cache
*egg-info
*_temp
16 changes: 16 additions & 0 deletions NEWS.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
Nevow 1.0 (2018-02-01)
======================

Features
--------

This release is compatible with python3, and actually incompatible with
python2.

- _flat.flatten no longer worries about encoding strings; this has
to be done by the write function passed.
- htmlfile and htmlstr are now aliases for xmlfile and xmlstr and
consequently require well-formed XML. This change results from the
microdom being effecively dropped from twisted.web for python3


Nevow 0.14.3 (2017-07-26)
=========================

Expand Down
6 changes: 3 additions & 3 deletions benchmarks/json_string_tokenizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def postOptions(self):
self['scale'] = int(self['scale'])


BASE = u'Hello, world. "Quotes".'
BASE = 'Hello, world. "Quotes".'
def benchmark(iterations, scale):
"""
Deserialize a string C{iterations} times. Make the string longer based
Expand All @@ -32,10 +32,10 @@ def benchmark(iterations, scale):
"""
s = serialize(BASE * scale)
before = time()
for i in xrange(iterations):
for i in range(iterations):
parse(s)
after = time()
print (after - before) / iterations, 'per call'
print((after - before) / iterations, 'per call')



Expand Down
62 changes: 62 additions & 0 deletions doc/strings_and_bytes.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
=====================================
Strings vs. Bytes in Nevow on python3
=====================================

Twisted.web decided to have represent several items in their Request
class – which is used quite frequently in nevow and exposed to user code
– as bytes. Also, at some point nevow has to produce bytes, as that is
what needs to go down the line.

In between, however, I'd like to keep out bytes as much as possible and
let people work with strings as far as possible. This document attempts
to delineate the string/bytes perimeter.

Given that, unfortunately, that perimeter is long and twisted, the plan
is to accept bytes and strings in several places (in particular, always
for URIs), where bytes, for these purposes, are supposed to be in a
(perhaps at some poin configurable) default encoding, which for now is
utf-8 independent of the enviroment.

Use utils.toBytes or utils.toString to turn function arguments into
strings or bytes as requrired.


Bytes within Twisted we're concerned with
=========================================

The most important items that are byte strings within request, include:

* uri
* keys and values in args (this hurts a lot)
* header keys (but header values are decoded)
* prePath -- this is where segments come from; segments, however, are
nevow interface and hence strings.
* the arguments to write (in nevow, we accept strings, too)


At least cred.checkers.InMemoryUsernamePasswordDatabaseDontUse
explicitly ASCII-encodes their usernames right now. Since that's
what's used in the unit tests, I'm following ASCII-encoded usernames
in guard. This seems insane. Anyone actually working with guard
should look into this.


Bytes usage within nevow itself
===============================

While flatteners still return strings, what is passed on to
twisted.web requests' write methods must, of course, be bytes.
nevow.appserver.Requests make that translation using utils.toBytes; user
code requiring non-UTF-8 encodings needs to translate to bytes itself at
this point.

Since renderHTTP can (and is, indeed, encouraged to) write strings and
the translation is done within nevow.Request.write (or similar),
Page.renderSynchronously and Page.renderString return strings rather
than bytes.

This is particularly relevant for unit tests: what is in the
FakeRequest's accumulator is bytes.


.. vim:tw=72
6 changes: 3 additions & 3 deletions examples/advanced_manualform/advanced_manualform.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def redirectAfterPost(aspects):
magicCookie = str(now())
refpath = refpath.replace('_nevow_carryover_', magicCookie)
_CARRYOVER[magicCookie] = C = tpc.Componentized()
for k, v in aspects.iteritems():
for k, v in aspects.items():
C.setComponent(k, v)
request.redirect(str(refpath))
from nevow import static
Expand Down Expand Up @@ -99,8 +99,8 @@ class Page(ManualFormMixin, rend.Page):
def form_post_btn1(self, what=None):
# 'what' is a keyword argument, and must be the same name that you
# give to the widget.
print "btn1:", what
print("btn1:", what)

def form_post_btn2(self, what=None):
# see above for 'what'.
print "btn2:", what
print("btn2:", what)
4 changes: 2 additions & 2 deletions examples/athenademo/benchmark.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

from __future__ import division


from twisted.python import filepath

Expand Down Expand Up @@ -31,7 +31,7 @@ def render_body(self, ctx, data):
yield top

class InitializationBenchmark(athena.LiveFragment):
jsClass = u'Nevow.Benchmarks.InitializationBenchmark'
jsClass = 'Nevow.Benchmarks.InitializationBenchmark'

docFactory = loaders.stan(
tags.div(render=tags.directive('liveFragment'))[
Expand Down
10 changes: 5 additions & 5 deletions examples/athenademo/calculator.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ class Calculator(object):
entered into the calculator. For example, if the buttons '3', '5', and
'+' have been pressed (in that order), C{expression} will be C{'35+'}.
"""
defaultExpression = u'0'
errorExpression = u'E'
defaultExpression = '0'
errorExpression = 'E'

def __init__(self):
self.expression = self.defaultExpression
Expand Down Expand Up @@ -57,7 +57,7 @@ def buttonClicked(self, symbol):
# Evaluate the expression
if symbol == '=':
try:
self.expression = unicode(eval(self.expression))
self.expression = str(eval(self.expression))
except ZeroDivisionError:
self.expression = self.errorExpression
return self.expression
Expand Down Expand Up @@ -86,7 +86,7 @@ class CalculatorElement(LiveElement):
"""
docFactory = xmlfile(sibling('calculator.html').path, 'CalculatorPattern')

jsClass = u"CalculatorDemo.Calculator"
jsClass = "CalculatorDemo.Calculator"

validSymbols = '0123456789/*-=+.C'

Expand Down Expand Up @@ -123,7 +123,7 @@ def __init__(self, *a, **kw):
# Update the mapping of known JavaScript modules so that the
# client-side code for this example can be found and served to the
# browser.
self.jsModules.mapping[u'CalculatorDemo'] = sibling(
self.jsModules.mapping['CalculatorDemo'] = sibling(
'calculator.js').path


Expand Down
18 changes: 9 additions & 9 deletions examples/athenademo/typeahead.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
from formless import annotate, webform
from twisted.python import util

animals = {u'elf' : u'Pointy ears. Bad attitude regarding trees.',
u'chipmunk': u'Cute. Fuzzy. Sings horribly.',
u'chupacabra': u'It sucks goats.',
u'ninja': u'Stealthy and invisible, and technically an animal.',
animals = {'elf' : 'Pointy ears. Bad attitude regarding trees.',
'chipmunk': 'Cute. Fuzzy. Sings horribly.',
'chupacabra': 'It sucks goats.',
'ninja': 'Stealthy and invisible, and technically an animal.',
}


Expand All @@ -26,18 +26,18 @@ class TypeAheadFieldFragment(athena.LiveFragment):
])

def loadDescription(self, typed):
if typed == u'':
return None, u'--'
if typed == '':
return None, '--'
matches = []
for key in animals:
if key.startswith(typed):
matches.append(key)
if len(matches) == 1:
return matches[0], animals[matches[0]]
elif len(matches) > 1:
return None, u"(Multiple found)"
return None, "(Multiple found)"
else:
return None, u'--'
return None, '--'
athena.expose(loadDescription)

class DataEntry(rend.Page):
Expand Down Expand Up @@ -75,7 +75,7 @@ def animals(self, animal, description):
return url.here

def data_animals(self, ctx, data):
return animals.keys()
return list(animals.keys())

def child_typeahead(self, ctx):
return TypeAheadPage(None, None)
Expand Down
9 changes: 5 additions & 4 deletions examples/athenademo/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from nevow import athena, loaders, static

class Clock(athena.LiveFragment):
jsClass = u"WidgetDemo.Clock"
jsClass = "WidgetDemo.Clock"

docFactory = loaders.xmlstr('''\
<div xmlns:nevow="http://nevow.com/ns/nevow/0.1"
Expand Down Expand Up @@ -49,7 +49,7 @@ def _oops(self, err):
self.running = False

def updateTime(self):
self.callRemote('setTime', unicode(time.ctime(), 'ascii')).addErrback(self._oops)
self.callRemote('setTime', str(time.ctime(), 'ascii')).addErrback(self._oops)

class WidgetPage(athena.LivePage):
docFactory = loaders.xmlstr("""\
Expand All @@ -73,14 +73,15 @@ class WidgetPage(athena.LivePage):

def __init__(self, *a, **kw):
super(WidgetPage, self).__init__(*a, **kw)
self.jsModules.mapping[u'WidgetDemo'] = util.sibpath(__file__, 'widgets.js')
self.jsModules.mapping['WidgetDemo'] = util.sibpath(__file__, 'widgets.js')

def childFactory(self, ctx, name):
ch = super(WidgetPage, self).childFactory(ctx, name)
if ch is None:
p = util.sibpath(__file__, name)
if os.path.exists(p):
ch = static.File(file(p))
with open(p) as f:
ch = static.File(f)
return ch

def render_clock(self, ctx, data):
Expand Down
12 changes: 6 additions & 6 deletions examples/blogengine/axiomstore.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from iblogengine import IBlog
from zope.interface import implements
from zope.interface import implementer
from axiom import item, store, attributes, sequence
from epsilon.extime import Time

Expand All @@ -24,8 +24,8 @@ def __init__(self, **kw):
def setModified(self):
self.modified = Time()

@implementer(IBlog)
class Blog(item.Item, item.InstallableMixin):
implements(IBlog)

typeName = "BlogengineBlog"
schemaVersion = 1
Expand All @@ -38,10 +38,10 @@ def __init__(self, **kw):
self.posts = sequence.List(store=self.store)
post = Post(store=self.store,
id=self.getNextId(),
author=u'mike',
title=u'FIRST POST!!!!',
category=u'Test',
content=u'I guess it worked.')
author='mike',
title='FIRST POST!!!!',
category='Test',
content='I guess it worked.')
self.addNewPost(post)

def installOn(self, other):
Expand Down
6 changes: 3 additions & 3 deletions examples/blogengine/email_client.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import sys, smtplib

fromaddr = raw_input("From: ")
toaddrs = raw_input("To: ").split(',')
print "Enter message, end with ^D:"
fromaddr = input("From: ")
toaddrs = input("To: ").split(',')
print("Enter message, end with ^D:")
msg = ''
while 1:
line = sys.stdin.readline()
Expand Down
34 changes: 17 additions & 17 deletions examples/blogengine/frontend.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from time import time as now
from zope.interface import implements, Interface
from zope.interface import implementer, Interface

from twisted.web import xmlrpc
from twisted.python.components import registerAdapter
Expand Down Expand Up @@ -49,9 +49,9 @@ def locateChild(self, ctx, segments):
class UI(BaseUI):

docFactory = loaders.xmlfile ('ui.html')
child_styles = static.File('styles')
child_styles = static.File('styles')
child_images = static.File('images')
child_webform_css = webform.defaultCSS
child_webform_css = webform.defaultCSS

def render_starttimer(self, ctx, data):
ctx.remember(now(), ITimer)
Expand Down Expand Up @@ -109,8 +109,8 @@ def child_thx(self, ctx):
return Thx()

##################################
@implementer(IInsert)
class NewEntry(BaseUI):
implements(IInsert)

docFactory = loaders.stan(
t.html[
Expand All @@ -132,10 +132,10 @@ def render_forms(self, ctx, data):
def insert(self, ctx, id, title, author, category, content):
newPost = Post(store=IStore(ctx),
id=int(id),
author=unicode(author),
title=unicode(title),
category=unicode(category),
content=unicode(content))
author=str(author),
title=str(title),
category=str(category),
content=str(content))
IBlog(IStore(ctx)).addNewPost(newPost)
inevow.IRequest(ctx).setComponent(iformless.IRedirectAfterPost, '/thx')

Expand All @@ -150,8 +150,8 @@ class Thx(rend.Page):
])

####################################
@implementer(IInsert)
class Entry(UI):
implements(IInsert)
def data_getEntries(self, ctx, data):
return [data]

Expand All @@ -165,10 +165,10 @@ def render_forms(self, ctx, data):
return webform.renderForms()

def insert(self, ctx, id, title, author, category, content):
self.original.author = unicode(author)
self.original.title = unicode(title)
self.original.category = unicode(category)
self.original.content = unicode(content)
self.original.author = str(author)
self.original.title = str(title)
self.original.category = str(category)
self.original.content = str(content)
inevow.IRequest(ctx).setComponent(iformless.IRedirectAfterPost, '/thx')

#####################################
Expand Down Expand Up @@ -213,10 +213,10 @@ def xmlrpc_publish(self, author, title, category, content):
newid = IBlog(self.store).getNextId()
newPost = Post(store=self.store,
id=newid,
author=unicode(author),
title=unicode(title),
category=unicode(category),
content=unicode(content))
author=str(author),
title=str(title),
category=str(category),
content=str(content))
IBlog(self.store).addNewPost(newPost)
return 'Successfully added post number %s' % newid
xmlrpc_publish = transacted(xmlrpc_publish)
Expand Down
Loading