Step 01: Most Basic Resource: Site Root

To remove some mystery about traversal, we start with the smallest possible step: an object at the top of our URL space. This object acts as the “root” and has a view which shows some data on that object.

Goals

  • Take a tiny step into traversal
  • Show how Pyramid grabs a resource object and makes it available in a view

Objectives

  • Make a factory for the root object
  • Pass it to the configurator
  • Have a view which displays an attribute on that object

Steps

  1. $ cd ../../resources; mkdir step01; cd step01

  2. Copy the following into step01/application.py:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    from wsgiref.simple_server import make_server
    
    from pyramid.config import Configurator
    
    from resources import bootstrap
    
    
    def main():
        config = Configurator(root_factory=bootstrap)
        config.scan("views")
        app = config.make_wsgi_app()
        return app
    
    
    if __name__ == '__main__':
        app = main()
        server = make_server(host='0.0.0.0', port=8080, app=app)
        server.serve_forever()
    
  3. Copy the following into step01/views.py:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    from pyramid.response import Response
    from pyramid.view import view_config
    
    class ProjectorViews(object):
        def __init__(self, context, request):
            self.context = context
            self.request = request
    
        @view_config()
        def default_view(self):
            body = "This SiteFolder is named: " + self.context.title
            return Response(body)
    
  4. Copy the following into step01/resources.py:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    class SiteFolder(dict):
        __name__ = ''
        __parent__ = None
    
        def __init__(self, title):
            self.title = title
    
    def bootstrap(request):
        root = SiteFolder('Projector Site')
    
        return root
    
  5. Copy the following into step01/tests.py:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    import unittest
    
    from pyramid.testing import DummyRequest
    from pyramid.testing import DummyResource
    
    class ProjectorViewsUnitTests(unittest.TestCase):
        def test_default_view(self):
            from views import ProjectorViews
    
            request = DummyRequest()
            title = "Dummy Context"
            context = DummyResource(title=title)
            inst = ProjectorViews(context, request)
            result = inst.default_view()
            self.failUnless('SiteFolder' in result.body)
            self.failUnless(title in result.body)
    
    
    class ProjectorFunctionalTests(unittest.TestCase):
        def setUp(self):
            from application import main
    
            app = main()
            from webtest import TestApp
    
            self.testapp = TestApp(app)
    
        def test_it(self):
            res = self.testapp.get('/', status=200)
            self.assertTrue('SiteFolder' in res.body)
            self.assertTrue('Projector Site' in res.body)
    
  6. $ nosetests should report running 2 tests.

  7. $ python application.py

  8. Open http://127.0.0.1:8080/ in your browser.

Extra Credit

  1. Is the root factory called once on startup, or on every request? Do a small change that answers this. What is the impact of the answer on this?

Analysis

Our application.py has a small but important change: we create the configuration with a root factory. Our root factory is a simple function that populates.

We put our resource objects in resources.py. Here we make the classes that model our application. We then have a bootstrap.py function which makes an instance of our class and hands back as the top of the tree.

In this step, our tree has one object: the root. It is an instance of SiteFolder. Since it is the root, it doesn’t need a __name__ (aka id) nor a __parent__ (reference to the container an object is in.)

Our site_view is passed, by Pyramid, the instance of this folder as context. The view can then grab attributes and other data from the object that is the focus of the URL.

Discussion

  • The concept of factories and their genesis going back to Zope and CMF
  • Pyramid and need for, and management of, __name__ and __parent__

Table Of Contents