You'd probably want to walk the iterable and cast all elements to string? Then do your join operation with the empty unicode string. Your code only checks the first item and assumes all other elements are also strings - perhaps your code is working because there is only one element in the iterable for your circumstances.
I'm not familiar enough with this part of the Pyramid library to say more than this.. but something must be casting to bytes somewhere otherwise all strings would be defaulting to Unicode under Python 3. On 21 Jul 2012, at 20:44, Andreas Reuleaux <[email protected]> wrote: > OK, I have a solution: if I patch the function > > render_view(context, request, name='', secure=True) > > in my .../pyramid-1.3.2-py3.2.egg/pyramid/view.py file > by replacing > > return ''.join(iterable) > > at the end with the following if-then-else code > > if isinstance(iterable[0], str): > return ''.join(iterable) > else: > return b''.join(iterable) > > then everything works as expected, but I'd certainly not > want to do this forever / would very much appreciate, if > someone could have a closer look at the problem. > > -Andreas > > > Andreas Reuleaux <[email protected]> writes: > >> OK, not having gotten any feedback, I guess my problem description was >> to vague. >> >> I have therefore prepared a little sample program, that should be easy >> to extract and run from this e-mail: when running it with python2 I have >> no problems, when running it with python3 I get the aforementioned byte >> vs. string problems (also shown below once more). >> >> While I roughly know, what has changed between python2 and python3 >> concerning strings/bytes, I am kind of stuck in this situation: I don't >> know what to do in this case and I would hope that someone will try out >> this sample program and point me in the right direction. >> >> To make the installation experience easier, I have avoided to use to >> many different python/configuration files: the whole program lives in >> one file sample.py, which make use of a couple of templates. >> >> To try out the program, you should therefore extract from this e-mail >> >> * the file sample.py >> >> * as well as the templates page.pt, home.pt, other.pt, and notfound.pt >> (note that only page.pt is a complete html page, the others are >> just html snippets) >> >> steps to install/run the program on python2 >> >> create the environment >> $ virtualenv foo >> $ cd foo >> $ ./bin/easy_install pyramid >> $ ./bin/easy_install pyramid_viewgroup >> >> copy the python script and the page templates to your foo env >> $ cp .../simple.py . >> $ cp .../page.pt . >> $ cp .../home.pt . >> $ cp .../other.pt . >> $ cp .../notfound.pt . >> >> adjust the path to the templates in simple.py, like >> path=os.path.dirname('/path/to/my/foo/') >> >> start the server >> $ ./bin/python simple.py -port 8080 >> >> and have a look at some pages >> http://myserver:8080/home >> http://myserver:8080/other >> http://myserver:8080/whatever - not found! >> http://myserver:8080/ - default view >> >> (see the explanations below, what's going on under the hood.) >> >> -- >> now do the same with python3 >> >> create the environment >> $ virtualenv-3.2 bar3 >> $ cd bar3 >> $ ./bin/easy_install-3.2 pyramid >> $ ./bin/easy_install-3.2 pyramid_viewgroup >> >> copy the simple.py script and the page templates as above, >> and adjust the path to the templates >> >> start the server with >> $ ./bin/python3 simple.py -port 8080 >> >> and have a look at some pages as above. >> >> While http://myserver:8080/, the default view renders fine, >> as soon as I look at some of the other pages: home, other, whatever (not >> found) >> I get >> >> File >> "/home/reuleaux/tmp/bar3/lib/python3.2/site-packages/pyramid-1.3.2-py3.2.egg/pyramid/view.py", >> line 139, in render_view >> return ''.join(iterable) >> TypeError: sequence item 0: expected str instance, bytes found >> >> - Expression: "provider('content')" >> - Filename: None >> - Location: (24:33) >> - Source: ... l:replace="structure provider('content')">page >> content</div> >> ^^^^^^^^^^^^^^^^^^^ >> - Arguments: repeat: {...} (0) >> renderer_name: /home/reuleaux/tmp/bar3/page.pt >> req: <NoneType - at 0x84bf40> >> request: <NoneType - at 0x84bf40> >> provider: <Provider - at 0x28059d0> >> renderer_info: <RendererHelper - at 0x2805a10> >> context: <Home - at 0x2805a50> >> escape: False >> view: <NoneType - at 0x84bf40> >> 192.168.1.7 - - [21/Jul/2012 01:58:49] "GET /home HTTP/1.1" 500 59 >> >> As mentioned before: I am lost in this case, any help is appreciated. >> >> Some explanations of what's going on in the python2 case / >> how it is supposed to work: >> >> While viewlets/content providers are not everyone's preferred style, >> I have used them here to assemble some pages from building blocks >> e. g. my home page looks just like this: >> >> @implementer(IPage) >> class Home(object): >> content=HomeContent() >> title='Home' >> >> I. e. it is a page (implements IPage), and its contents is just >> the home content. >> >> Another page, Other, is very similar, but has of course some other >> content: >> >> @implementer(IPage) >> class Other(object): >> content=OtherContent() >> title='Other' >> >> I have used traversal to find those objects, e. g. >> >> http://myserver:port/home >> >> will render Home, .../other will render Other and so on >> >> The views operate just on the interfaces IPage, IContent, >> i. e. view_page can render any page, and will make use of >> view_content to fill in / show the content provided for >> this particular page. >> >> >> Anyway, thanks for reading, and thanks in advance for trying out. >> >> >> -Andreas >> >> >> simple.py >> -------------------------------------------------- >> from wsgiref.simple_server import make_server >> from pyramid.config import Configurator >> from pyramid.response import Response >> >> from pyramid_viewgroup import Provider >> >> from pyramid.renderers import render_to_response >> >> import sys >> import os >> >> import argparse >> >> >> opts=None >> >> >> # path = os.path.dirname('/home/reuleaux/tmp/foo/') >> path = os.path.dirname('/home/reuleaux/work/website/py3/') >> >> >> >> from zope.interface import Interface, implementer >> >> >> class IContent(Interface): >> pass >> >> >> class IPage(Interface): >> pass >> >> >> @implementer(IContent) >> class HomeContent(object): >> msg="hi from home" >> tmplt=os.path.join(path, 'home.pt') >> >> >> @implementer(IPage) >> class Home(object): >> content=HomeContent() >> title='Home' >> >> >> @implementer(IContent) >> class OtherContent(object): >> msg="hi from other" >> tmplt=os.path.join(path, 'other.pt') >> >> >> @implementer(IPage) >> class Other(object): >> content=OtherContent() >> title='Other' >> >> >> @implementer(IContent) >> class NotFoundContent(object): >> tmplt=os.path.join(path, 'notfound.pt') >> msg="not found!" >> >> >> @implementer(IPage) >> class NotFound(object): >> content=NotFoundContent() >> title='not found' >> >> >> >> app={ >> 'home': Home, >> 'other': Other, >> } >> >> >> @implementer(IPage) >> class App(object): >> def __getitem__(self, name): >> return app.get(name, NotFound)() >> >> >> class Root(object): >> def __init__(self, request): >> self.request = request >> >> def __getitem__(self, name=None): >> if name in ['static', >> ]: >> raise KeyError >> else: >> return App()[name] >> >> >> >> >> def default_view(request): >> return Response('Hello world!') >> >> >> >> >> >> def content_view(request): >> content=getattr(request.context, 'content', None) >> >> if hasattr(content, 'tmplt'): >> return render_to_response(content.tmplt, >> { }, >> ) >> else: >> return Response('<span class="mark">content</span>') >> >> >> def page_view(request): >> context=request.context >> provider=Provider(context, request) >> return render_to_response( >> os.path.join(path, 'page.pt'), >> { >> 'provider': provider, >> 'context': context, >> }, >> ) >> >> >> >> >> def parser(): >> >> parser=argparse.ArgumentParser() >> >> parser.add_argument("-port", >> '--port', >> dest="port", >> action="store", >> default=6543, >> help="port") >> >> return parser >> >> >> def run(args): >> >> p=parser() >> global opts >> opts = p.parse_args(args) >> # print(opts) >> >> config = Configurator(root_factory=Root) >> >> >> config.add_view('.default_view',) >> >> config.add_view('.page_view', >> context='.IPage',) >> >> >> config.add_view('.content_view', >> name='content', >> context='.IPage',) >> >> >> app = config.make_wsgi_app() >> server = make_server('0.0.0.0', int(opts.port), app) >> server.serve_forever() >> >> >> if __name__ == '__main__': >> run(sys.argv[1:]) >> -------------------------------------------------- >> >> >> >> >> >> page.pt >> -------------------------------------------------- >> <?xml version="1.0" encoding="utf-8"?> >> >> <html xmlns="http://www.w3.org/1999/xhtml" >> xmlns:tal="http://xml.zope.org/namespaces/tal" >>> >> <head> >> <title>${context.title}</title> >> >> <style type="text/css" >> media="screen"> >> .mark { >> font-weight: bold; >> font-style: italic; >> } >> </style> >> >> >> </head> >> <body> >> <p>any page will have this structure</p> >> >> <p>and here comes the content:</p> >> >> <div tal:replace="structure provider('content')">page content</div> >> >> <p>rest of the page...</p> >> >> </body> >> </html> >> -------------------------------------------------- >> >> >> >> >> home.pt >> -------------------------------------------------- >> <div >> xmlns:tal="http://xml.zope.org/namespaces/tal" >> tal:omit-tag="" >>> >> >> >> <p> >> this is my <span class="mark">home page</span>... >> </p> >> >> >> </div> >> -------------------------------------------------- >> >> >> >> >> >> other.pt >> -------------------------------------------------- >> <div >> xmlns:tal="http://xml.zope.org/namespaces/tal" >> tal:omit-tag="" >>> >> >> >> <p> >> this is my <span class="mark">other page</span> >> </p> >> >> >> </div> >> -------------------------------------------------- >> >> >> >> >> notfound.pt >> -------------------------------------------------- >> <div >> xmlns:tal="http://xml.zope.org/namespaces/tal" >> tal:omit-tag="" >>> >> >> Sorry, page not found >> >> </div> >> -------------------------------------------------- > > -- > You received this message because you are subscribed to the Google Groups > "pylons-discuss" group. > 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/pylons-discuss?hl=en. > -- You received this message because you are subscribed to the Google Groups "pylons-discuss" group. 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/pylons-discuss?hl=en.
