diff options
| author | Chris McDonough <chrism@plope.com> | 2011-11-27 04:08:20 -0500 |
|---|---|---|
| committer | Chris McDonough <chrism@plope.com> | 2011-11-27 04:08:20 -0500 |
| commit | 5edd54f05b05330fa6e899a1bb1650cc7a2df33c (patch) | |
| tree | dfbeed48fc684717b3f6a5ed7a28fd5fbb1e3479 /docs/tutorials/wiki2/src/authorization | |
| parent | 596495de4aa1ab0f3a3752d21c14ac08631e8457 (diff) | |
| download | pyramid-5edd54f05b05330fa6e899a1bb1650cc7a2df33c.tar.gz pyramid-5edd54f05b05330fa6e899a1bb1650cc7a2df33c.tar.bz2 pyramid-5edd54f05b05330fa6e899a1bb1650cc7a2df33c.zip | |
- The SQLAlchemy Wiki tutorial has been updated. It now uses
``@view_config`` decorators and an explicit database population script.
Closes #359.
Diffstat (limited to 'docs/tutorials/wiki2/src/authorization')
12 files changed, 145 insertions, 105 deletions
diff --git a/docs/tutorials/wiki2/src/authorization/README.txt b/docs/tutorials/wiki2/src/authorization/README.txt index d41f7f90f..6f851e9b7 100644 --- a/docs/tutorials/wiki2/src/authorization/README.txt +++ b/docs/tutorials/wiki2/src/authorization/README.txt @@ -1,4 +1 @@ tutorial README - - - diff --git a/docs/tutorials/wiki2/src/authorization/development.ini b/docs/tutorials/wiki2/src/authorization/development.ini index d1e262324..4f7493cba 100644 --- a/docs/tutorials/wiki2/src/authorization/development.ini +++ b/docs/tutorials/wiki2/src/authorization/development.ini @@ -1,5 +1,6 @@ [app:main] use = egg:tutorial + pyramid.reload_templates = true pyramid.debug_authorization = false pyramid.debug_notfound = false @@ -19,7 +20,7 @@ port = 6543 # Begin logging configuration [loggers] -keys = root, sqlalchemy +keys = root, tutorial, sqlalchemy [handlers] keys = console @@ -31,6 +32,11 @@ keys = generic level = INFO handlers = console +[logger_tutorial] +level = DEBUG +handlers = +qualname = tutorial + [logger_sqlalchemy] level = INFO handlers = diff --git a/docs/tutorials/wiki2/src/authorization/production.ini b/docs/tutorials/wiki2/src/authorization/production.ini index ac02acf3f..53eaf20a1 100644 --- a/docs/tutorials/wiki2/src/authorization/production.ini +++ b/docs/tutorials/wiki2/src/authorization/production.ini @@ -1,5 +1,6 @@ [app:main] use = egg:tutorial + pyramid.reload_templates = false pyramid.debug_authorization = false pyramid.debug_notfound = false diff --git a/docs/tutorials/wiki2/src/authorization/setup.py b/docs/tutorials/wiki2/src/authorization/setup.py index 439a86923..09769bfff 100644 --- a/docs/tutorials/wiki2/src/authorization/setup.py +++ b/docs/tutorials/wiki2/src/authorization/setup.py @@ -42,6 +42,7 @@ setup(name='tutorial', entry_points = """\ [paste.app_factory] main = tutorial:main + [console_scripts] + populate_tutorial = tutorial.scripts.populate:main """, ) - diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/__init__.py b/docs/tutorials/wiki2/src/authorization/tutorial/__init__.py index cca52fdfe..04dd5fe82 100644 --- a/docs/tutorials/wiki2/src/authorization/tutorial/__init__.py +++ b/docs/tutorials/wiki2/src/authorization/tutorial/__init__.py @@ -4,14 +4,15 @@ from pyramid.authorization import ACLAuthorizationPolicy from sqlalchemy import engine_from_config -from tutorial.models import initialize_sql from tutorial.security import groupfinder +from .models import DBSession + def main(global_config, **settings): - """ This function returns a WSGI application. + """ This function returns a Pyramid WSGI application. """ engine = engine_from_config(settings, 'sqlalchemy.') - initialize_sql(engine) + DBSession.configure(bind=engine) authn_policy = AuthTktAuthenticationPolicy( 'sosecret', callback=groupfinder) authz_policy = ACLAuthorizationPolicy() @@ -19,27 +20,13 @@ def main(global_config, **settings): root_factory='tutorial.models.RootFactory', authentication_policy=authn_policy, authorization_policy=authz_policy) - config.add_static_view('static', 'tutorial:static', cache_max_age=3600) - + config.add_static_view('static', 'static', cache_max_age=3600) config.add_route('view_wiki', '/') config.add_route('login', '/login') config.add_route('logout', '/logout') config.add_route('view_page', '/{pagename}') config.add_route('add_page', '/add_page/{pagename}') config.add_route('edit_page', '/{pagename}/edit_page') - - config.add_view('tutorial.views.view_wiki', route_name='view_wiki') - config.add_view('tutorial.login.login', route_name='login', - renderer='tutorial:templates/login.pt') - config.add_view('tutorial.login.logout', route_name='logout') - config.add_view('tutorial.views.view_page', route_name='view_page', - renderer='tutorial:templates/view.pt') - config.add_view('tutorial.views.add_page', route_name='add_page', - renderer='tutorial:templates/edit.pt', permission='edit') - config.add_view('tutorial.views.edit_page', route_name='edit_page', - renderer='tutorial:templates/edit.pt', permission='edit') - config.add_view('tutorial.login.login', - context='pyramid.httpexceptions.HTTPForbidden', - renderer='tutorial:templates/login.pt') + config.scan() return config.make_wsgi_app() diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/login.py b/docs/tutorials/wiki2/src/authorization/tutorial/login.py deleted file mode 100644 index 5a825d8d6..000000000 --- a/docs/tutorials/wiki2/src/authorization/tutorial/login.py +++ /dev/null @@ -1,37 +0,0 @@ -from pyramid.httpexceptions import HTTPFound -from pyramid.security import remember -from pyramid.security import forget - -from tutorial.security import USERS - -def login(request): - login_url = request.route_url('login') - referrer = request.url - if referrer == login_url: - referrer = '/' # never use the login form itself as came_from - came_from = request.params.get('came_from', referrer) - message = '' - login = '' - password = '' - if 'form.submitted' in request.params: - login = request.params['login'] - password = request.params['password'] - if USERS.get(login) == password: - headers = remember(request, login) - return HTTPFound(location = came_from, - headers = headers) - message = 'Failed login' - - return dict( - message = message, - url = request.application_url + '/login', - came_from = came_from, - login = login, - password = password, - ) - -def logout(request): - headers = forget(request) - return HTTPFound(location = request.route_url('view_wiki'), - headers = headers) - diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/models.py b/docs/tutorials/wiki2/src/authorization/tutorial/models.py index 832545cb1..c3bdcbea5 100644 --- a/docs/tutorials/wiki2/src/authorization/tutorial/models.py +++ b/docs/tutorials/wiki2/src/authorization/tutorial/models.py @@ -1,17 +1,20 @@ -import transaction +from pyramid.security import ( + Allow, + Everyone, + ) -from pyramid.security import Allow -from pyramid.security import Everyone +from sqlalchemy import ( + Column, + Integer, + Text, + ) -from sqlalchemy import Column -from sqlalchemy import Integer -from sqlalchemy import Text - -from sqlalchemy.exc import IntegrityError from sqlalchemy.ext.declarative import declarative_base -from sqlalchemy.orm import scoped_session -from sqlalchemy.orm import sessionmaker +from sqlalchemy.orm import ( + scoped_session, + sessionmaker, + ) from zope.sqlalchemy import ZopeTransactionExtension @@ -29,20 +32,6 @@ class Page(Base): self.name = name self.data = data -def initialize_sql(engine): - DBSession.configure(bind=engine) - Base.metadata.bind = engine - Base.metadata.create_all(engine) - try: - transaction.begin() - session = DBSession() - page = Page('FrontPage', 'This is the front page') - session.add(page) - transaction.commit() - except IntegrityError: - # already created - transaction.abort() - class RootFactory(object): __acl__ = [ (Allow, Everyone, 'view'), (Allow, 'group:editors', 'edit') ] diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/scripts/__init__.py b/docs/tutorials/wiki2/src/authorization/tutorial/scripts/__init__.py new file mode 100644 index 000000000..5bb534f79 --- /dev/null +++ b/docs/tutorials/wiki2/src/authorization/tutorial/scripts/__init__.py @@ -0,0 +1 @@ +# package diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/scripts/populate.py b/docs/tutorials/wiki2/src/authorization/tutorial/scripts/populate.py new file mode 100644 index 000000000..981adff38 --- /dev/null +++ b/docs/tutorials/wiki2/src/authorization/tutorial/scripts/populate.py @@ -0,0 +1,35 @@ +import os +import sys +import transaction + +from sqlalchemy import engine_from_config + +from pyramid.paster import ( + get_appsettings, + setup_logging, + ) + +from ..models import ( + DBSession, + Page, + Base, + ) + +def usage(argv): + cmd = os.path.basename(argv[0]) + print('usage: %s <config_uri>\n' + '(example: "%s development.ini")' % (cmd, cmd)) + sys.exit(1) + +def main(argv=sys.argv, settings=None): + if len(argv) != 2: + usage(argv) + config_uri = argv[1] + setup_logging(config_uri) + settings = get_appsettings(config_uri) + engine = engine_from_config(settings, 'sqlalchemy.') + DBSession.configure(bind=engine) + Base.metadata.create_all(engine) + with transaction.manager: + model = Page('FrontPage', 'This is the front page') + DBSession.add(model) diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/security.py b/docs/tutorials/wiki2/src/authorization/tutorial/security.py index cfd13071e..d88c9c71f 100644 --- a/docs/tutorials/wiki2/src/authorization/tutorial/security.py +++ b/docs/tutorials/wiki2/src/authorization/tutorial/security.py @@ -5,4 +5,3 @@ GROUPS = {'editor':['group:editors']} def groupfinder(userid, request): if userid in USERS: return GROUPS.get(userid, []) - diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/tests.py b/docs/tutorials/wiki2/src/authorization/tutorial/tests.py index 332031ba4..31d2dc6d5 100644 --- a/docs/tutorials/wiki2/src/authorization/tutorial/tests.py +++ b/docs/tutorials/wiki2/src/authorization/tutorial/tests.py @@ -1,15 +1,20 @@ import unittest - +import transaction from pyramid import testing def _initTestingDB(): - from tutorial.models import DBSession - from tutorial.models import Base from sqlalchemy import create_engine + from tutorial.models import ( + DBSession, + Page, + Base + ) engine = create_engine('sqlite://') - DBSession.configure(bind=engine) - Base.metadata.bind = engine Base.metadata.create_all(engine) + DBSession.configure(bind=engine) + with transaction.manager: + model = Page('FrontPage', 'This is the front page') + DBSession.add(model) return DBSession def _registerRoutes(config): @@ -20,14 +25,16 @@ def _registerRoutes(config): class ViewWikiTests(unittest.TestCase): def setUp(self): self.config = testing.setUp() + self.session = _initTestingDB() def tearDown(self): + self.session.remove() testing.tearDown() def _callFUT(self, request): from tutorial.views import view_wiki return view_wiki(request) - + def test_it(self): _registerRoutes(self.config) request = testing.DummyRequest() @@ -40,6 +47,7 @@ class ViewPageTests(unittest.TestCase): self.config = testing.setUp() def tearDown(self): + self.session.remove() testing.tearDown() def _callFUT(self, request): @@ -121,7 +129,8 @@ class EditPageTests(unittest.TestCase): self.session.add(page) info = self._callFUT(request) self.assertEqual(info['page'], page) - self.assertEqual(info['save_url'], 'http://example.com/abc/edit_page') + self.assertEqual(info['save_url'], + 'http://example.com/abc/edit_page') def test_it_submitted(self): from tutorial.models import Page diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/views.py b/docs/tutorials/wiki2/src/authorization/tutorial/views.py index fc85d4585..375f1f5a5 100644 --- a/docs/tutorials/wiki2/src/authorization/tutorial/views.py +++ b/docs/tutorials/wiki2/src/authorization/tutorial/views.py @@ -1,20 +1,36 @@ import re - from docutils.core import publish_parts -from pyramid.httpexceptions import HTTPFound, HTTPNotFound -from pyramid.security import authenticated_userid +from pyramid.httpexceptions import ( + HTTPFound, + HTTPNotFound, + HTTPForbidden, + ) + +from pyramid.view import view_config + +from pyramid.security import ( + remember, + forget, + authenticated_userid, + ) -from tutorial.models import DBSession -from tutorial.models import Page +from .models import ( + DBSession, + Page, + ) + +from .security import USERS # regular expression used to find WikiWords wikiwords = re.compile(r"\b([A-Z]\w+[A-Z]+\w+)") +@view_config(route_name='view_wiki') def view_wiki(request): return HTTPFound(location = request.route_url('view_page', pagename='FrontPage')) +@view_config(route_name='view_page', renderer='templates/view.pt') def view_page(request): pagename = request.matchdict['pagename'] session = DBSession() @@ -35,10 +51,11 @@ def view_page(request): content = publish_parts(page.data, writer_name='html')['html_body'] content = wikiwords.sub(check, content) edit_url = request.route_url('edit_page', pagename=pagename) - logged_in = authenticated_userid(request) return dict(page=page, content=content, edit_url=edit_url, - logged_in=logged_in) + logged_in=authenticated_userid(request)) +@view_config(route_name='add_page', renderer='templates/edit.pt', + permission='edit') def add_page(request): name = request.matchdict['pagename'] if 'form.submitted' in request.params: @@ -50,9 +67,11 @@ def add_page(request): pagename=name)) save_url = request.route_url('add_page', pagename=name) page = Page('', '') - logged_in = authenticated_userid(request) - return dict(page=page, save_url=save_url, logged_in=logged_in) + return dict(page=page, save_url=save_url, + logged_in=authenticated_userid(request)) +@view_config(route_name='edit_page', renderer='templates/edit.pt', + permission='edit') def edit_page(request): name = request.matchdict['pagename'] session = DBSession() @@ -62,10 +81,43 @@ def edit_page(request): session.add(page) return HTTPFound(location = request.route_url('view_page', pagename=name)) - - logged_in = authenticated_userid(request) return dict( page=page, save_url = request.route_url('edit_page', pagename=name), - logged_in = logged_in, + logged_in=authenticated_userid(request), ) + +@view_config(route_name='login', renderer='templates/login.pt') +@view_config(context=HTTPForbidden, renderer='templates/login.pt') +def login(request): + login_url = request.route_url('login') + referrer = request.url + if referrer == login_url: + referrer = '/' # never use the login form itself as came_from + came_from = request.params.get('came_from', referrer) + message = '' + login = '' + password = '' + if 'form.submitted' in request.params: + login = request.params['login'] + password = request.params['password'] + if USERS.get(login) == password: + headers = remember(request, login) + return HTTPFound(location = came_from, + headers = headers) + message = 'Failed login' + + return dict( + message = message, + url = request.application_url + '/login', + came_from = came_from, + login = login, + password = password, + ) + +@view_config(route_name='logout') +def logout(request): + headers = forget(request) + return HTTPFound(location = request.route_url('view_wiki'), + headers = headers) + |
