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

Default renderer can fail to setup properly #249

Closed
mLewisLogic opened this Issue Aug 8, 2011 · 8 comments

Comments

Projects
None yet
3 participants
@mLewisLogic

mLewisLogic commented Aug 8, 2011

Situation:

init.py

default renderer setup in config

config.add_renderer(None, json_renderer_factory)

views.py

@view_config(name='a', context=AEndpoint, permission='everyone')
def a(request):
return {}

@view_config(route_name='b', renderer='api:templates/b.pt')
def b(request):
return {}

Note: A is setup on traversal, while B is dispatch
If I start the server, then load A first, everything works fine.
If I start the server, then load B first, subsequent calls to A fail with:

File '/srv/spoton/lib/python2.7/site-packages/WebError-0.10.3-py2.7.egg/weberror/evalexception.py', line 431 in respond
app_iter = self.application(environ, detect_start_response)
File '/srv/spoton/lib/python2.7/site-packages/pyramid/router.py', line 161 in call
response = view_callable(context, request)
File '/srv/spoton/lib/python2.7/site-packages/pyramid/config.py', line 3022 in _secured_view
return view(context, request)
File '/srv/spoton/lib/python2.7/site-packages/pyramid/config.py', line 3140 in rendered_view
context)
File '/srv/spoton/lib/python2.7/site-packages/pyramid/renderers.py', line 384 in render_view
return self.render_to_response(response, system, request=request)
File '/srv/spoton/lib/python2.7/site-packages/pyramid/renderers.py', line 411 in render_to_response
result = self.render(value, system_values, request=request)
File '/srv/spoton/lib/python2.7/site-packages/pyramid/renderers.py', line 387 in render
renderer = self.renderer
File '/srv/spoton/lib/python2.7/site-packages/pyramid/decorator.py', line 17 in get
val = self.wrapped(inst)
File '/srv/spoton/lib/python2.7/site-packages/pyramid/renderers.py', line 370 in renderer
'No such renderer factory %s' % str(self.type))
ValueError: No such renderer factory None

@mLewisLogic

This comment has been minimized.

Show comment
Hide comment
@mLewisLogic

mLewisLogic Aug 8, 2011

This is when running via paster. Haven't tried any other webservers.

mLewisLogic commented Aug 8, 2011

This is when running via paster. Haven't tried any other webservers.

@mcdonc

This comment has been minimized.

Show comment
Hide comment
@mcdonc

mcdonc Aug 10, 2011

Member

Sure enough, I can replicate this behavior with the following script (using the Pyramid trunk):

from pyramid.view import view_config
from pyramid.config import Configurator
from pyramid.renderers import json_renderer_factory
from paste.httpserver import serve

class Root(object):
    def __init__(self, request):
        pass

@view_config(name='a', context=Root, permission='everyone')
def a(request):
    return {}

@view_config(route_name='b', renderer='__main__:foo.pt')
def b(request):
    return {}


if __name__ == '__main__':
    config = Configurator(root_factory=Root)
    config.add_renderer(None, json_renderer_factory)
    config.add_route('b', '/b')
    config.scan('__main__')
    serve(config.make_wsgi_app())

# foo.pt in same directory:
# <html>
# </html>
Member

mcdonc commented Aug 10, 2011

Sure enough, I can replicate this behavior with the following script (using the Pyramid trunk):

from pyramid.view import view_config
from pyramid.config import Configurator
from pyramid.renderers import json_renderer_factory
from paste.httpserver import serve

class Root(object):
    def __init__(self, request):
        pass

@view_config(name='a', context=Root, permission='everyone')
def a(request):
    return {}

@view_config(route_name='b', renderer='__main__:foo.pt')
def b(request):
    return {}


if __name__ == '__main__':
    config = Configurator(root_factory=Root)
    config.add_renderer(None, json_renderer_factory)
    config.add_route('b', '/b')
    config.scan('__main__')
    serve(config.make_wsgi_app())

# foo.pt in same directory:
# <html>
# </html>
@mcdonc

This comment has been minimized.

Show comment
Hide comment
@mcdonc

mcdonc Aug 10, 2011

Member

Simplified:


from pyramid.config import Configurator
from pyramid.renderers import json_renderer_factory
from paste.httpserver import serve

def a(request):
    return {}

def b(request):
    return {}

if __name__ == '__main__':
    config = Configurator()
    config.add_renderer(None, json_renderer_factory)
    config.add_route('b', '/b')
    config.add_view(a, name='a')
    config.add_view(b, route_name='b', renderer='__main__:foo.pt')
    serve(config.make_wsgi_app())

# foo.pt in same directory:
# <html>
# </html>

Note: does not fail if renderer='string' instead of renderer='main:foo.pt'

Member

mcdonc commented Aug 10, 2011

Simplified:


from pyramid.config import Configurator
from pyramid.renderers import json_renderer_factory
from paste.httpserver import serve

def a(request):
    return {}

def b(request):
    return {}

if __name__ == '__main__':
    config = Configurator()
    config.add_renderer(None, json_renderer_factory)
    config.add_route('b', '/b')
    config.add_view(a, name='a')
    config.add_view(b, route_name='b', renderer='__main__:foo.pt')
    serve(config.make_wsgi_app())

# foo.pt in same directory:
# <html>
# </html>

Note: does not fail if renderer='string' instead of renderer='main:foo.pt'

@cguardia

This comment has been minimized.

Show comment
Hide comment
@cguardia

cguardia Aug 10, 2011

Member

Chris, I thought you meant a script for reproducing it without pyramid...sorry I made you work extra.

FWIW I did a very similar script and found out that when visiting 'b' first, the default renderer is in the registry until we get to this line:

https://github.com/Pylons/pyramid/blob/master/pyramid/renderers.py#L336

After that, the registry query for (IRenderer, None) comes empty, so a visit to 'a' fails from then on. Visiting 'a' first works because renderer is a reified property and it gets stored as an attribute after that visit.

Member

cguardia commented Aug 10, 2011

Chris, I thought you meant a script for reproducing it without pyramid...sorry I made you work extra.

FWIW I did a very similar script and found out that when visiting 'b' first, the default renderer is in the registry until we get to this line:

https://github.com/Pylons/pyramid/blob/master/pyramid/renderers.py#L336

After that, the registry query for (IRenderer, None) comes empty, so a visit to 'a' fails from then on. Visiting 'a' first works because renderer is a reified property and it gets stored as an attribute after that visit.

@mcdonc

This comment has been minimized.

Show comment
Hide comment
@mcdonc

mcdonc Aug 10, 2011

Member

Yeah sorry Carlos, I didn't know what you were trying was related to Pyramid at all. No extra work got done, no worries ;) Thanks for the tip about where things go pear-shaped, that should help me track it down,

Member

mcdonc commented Aug 10, 2011

Yeah sorry Carlos, I didn't know what you were trying was related to Pyramid at all. No extra work got done, no worries ;) Thanks for the tip about where things go pear-shaped, that should help me track it down,

@mcdonc

This comment has been minimized.

Show comment
Hide comment
@mcdonc

mcdonc Aug 10, 2011

Member

Hilarious. Adding this line causes the problem to disappear:


[chrism@thinko pyramid]$ git diff
diff --git a/pyramid/renderers.py b/pyramid/renderers.py
index a06067c..f6e293b 100644
--- a/pyramid/renderers.py
+++ b/pyramid/renderers.py
@@ -393,6 +393,7 @@ class RendererHelper(object):
         return self.render_to_response(response, system, request=request)

     def render(self, value, system_values, request=None):
+        print self.registry.queryUtility(IRendererFactory)
         renderer = self.renderer
         if system_values is None:
             system_values = {
Member

mcdonc commented Aug 10, 2011

Hilarious. Adding this line causes the problem to disappear:


[chrism@thinko pyramid]$ git diff
diff --git a/pyramid/renderers.py b/pyramid/renderers.py
index a06067c..f6e293b 100644
--- a/pyramid/renderers.py
+++ b/pyramid/renderers.py
@@ -393,6 +393,7 @@ class RendererHelper(object):
         return self.render_to_response(response, system, request=request)

     def render(self, value, system_values, request=None):
+        print self.registry.queryUtility(IRendererFactory)
         renderer = self.renderer
         if system_values is None:
             system_values = {
@mcdonc

This comment has been minimized.

Show comment
Hide comment
@mcdonc

mcdonc Aug 10, 2011

Member

The smallest fix I can come up with is this:

[chrism@thinko pyramid]$ git diff
diff --git a/pyramid/renderers.py b/pyramid/renderers.py
index a06067c..94ec74c 100644
--- a/pyramid/renderers.py
+++ b/pyramid/renderers.py
@@ -354,7 +354,7 @@ class RendererHelper(object):
         if name and '.' in name:
             rtype = os.path.splitext(name)[1]
         else:
-            rtype = name
+            rtype = name or ''

         if registry is None:
             registry = get_current_registry()
Member

mcdonc commented Aug 10, 2011

The smallest fix I can come up with is this:

[chrism@thinko pyramid]$ git diff
diff --git a/pyramid/renderers.py b/pyramid/renderers.py
index a06067c..94ec74c 100644
--- a/pyramid/renderers.py
+++ b/pyramid/renderers.py
@@ -354,7 +354,7 @@ class RendererHelper(object):
         if name and '.' in name:
             rtype = os.path.splitext(name)[1]
         else:
-            rtype = name
+            rtype = name or ''

         if registry is None:
             registry = get_current_registry()

@mcdonc mcdonc closed this in 1939d00 Aug 10, 2011

@mLewisLogic

This comment has been minimized.

Show comment
Hide comment
@mLewisLogic

mLewisLogic Aug 12, 2011

Confirmed fix. Thanks guys!

mLewisLogic commented Aug 12, 2011

Confirmed fix. Thanks guys!

biosyssun pushed a commit to biosyssun/pyramid that referenced this issue Dec 13, 2014

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment