OK, I found a workaround/solution:

Instead of patching render_view() in
.../pyramid-1.3.2-py3.2.egg/pyramid/view.py I am overriding Providers'
__call__() method with my own my_render_view() function now like so:

  from pyramid.view import render_view_to_iterable

  # cf. pyramid-1.3.2-py3.2.egg/pyramid/view.py
  def my_render_view(context, request, name, secure):
      iterable = render_view_to_iterable(context, request, name, secure)
      if iterable is None:
          return None

      # rx
      # return ''.join(iterable)
      if isinstance(iterable[0], str):
          return ''.join(iterable)
      else:
          return b''.join(iterable)


  from pyramid_viewgroup import Provider

  class MyProvider(Provider):

      def __call__(self, name='', secure=True):
          return my_render_view(self.context, self.request, name, secure)

then I use this MyProvider (instead of just Provider formerly) 
in page_view():


  def page_view(request):
      context=request.context
      # provider=Provider(context, request)
      provider=MyProvider(context, request)
      return render_to_response(
          os.path.join(path, 'page.pt'),
          {
              'provider': provider,
              'context': context,
          },
      )
   
While there still might be a better / easier solution
- and I would like to here about it - this workaround
at least allows my to use pyramid_viegroup in the way
I used to in python2.x

My guess is still, that noone else has bothered to
try pyramid_viewgroup on python3.

-Andreas


Andreas Reuleaux <[email protected]> writes:

> Well, yes you are right, seems to work in my case, because all entries
> in the iterable are bytes (but haven't even bothered to see how many
> entries there are in my iterable).
>
> But the real thing is: I don't want to mess at all with
> patching the pyramid source, I just want to use its api properly,
> and if it doesn't work, 
>
> * then this could either be a flaw in my
>   program / usage of the pyramid api
>   - and I'd hope that someone would point me
>   in the right direction of how to do it better - maybe there is some
>   magic to use when working with python3?
>
> * or there could be a flaw in the pyramid / pyramid_viewlet
>   source - I guess, that can only be answered by someone
>   familiar with the source
>
> Anyway, thanks for answering.
>
> -Andreas
>
>
> Simon Yarde <[email protected]> writes:
>
>> 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.

Reply via email to