summaryrefslogtreecommitdiff
path: root/docs/tutorials/wiki/src/tests
diff options
context:
space:
mode:
authorChristoph Zwerschke <cito@online.de>2016-04-19 20:07:12 +0200
committerChristoph Zwerschke <cito@online.de>2016-04-19 20:07:12 +0200
commit3629c49e46207ff5162a82883c14937e6ef4c186 (patch)
tree1306181202cb8313f16080789f5b9ab1eeb61d53 /docs/tutorials/wiki/src/tests
parent804ba0b2f434781e77d2b5191f1cd76a490f6610 (diff)
parent6c16fb020027fac47e4d2e335cd9e264dba8aa3b (diff)
downloadpyramid-3629c49e46207ff5162a82883c14937e6ef4c186.tar.gz
pyramid-3629c49e46207ff5162a82883c14937e6ef4c186.tar.bz2
pyramid-3629c49e46207ff5162a82883c14937e6ef4c186.zip
Merge remote-tracking branch 'refs/remotes/Pylons/master'
Diffstat (limited to 'docs/tutorials/wiki/src/tests')
-rw-r--r--docs/tutorials/wiki/src/tests/CHANGES.txt4
-rw-r--r--docs/tutorials/wiki/src/tests/MANIFEST.in2
-rw-r--r--docs/tutorials/wiki/src/tests/README.txt12
-rw-r--r--docs/tutorials/wiki/src/tests/development.ini65
-rw-r--r--docs/tutorials/wiki/src/tests/production.ini60
-rw-r--r--docs/tutorials/wiki/src/tests/setup.py54
-rw-r--r--docs/tutorials/wiki/src/tests/tutorial/__init__.py27
-rw-r--r--docs/tutorials/wiki/src/tests/tutorial/models.py29
-rw-r--r--docs/tutorials/wiki/src/tests/tutorial/security.py7
-rw-r--r--docs/tutorials/wiki/src/tests/tutorial/static/pyramid-16x16.pngbin0 -> 1319 bytes
-rw-r--r--docs/tutorials/wiki/src/tests/tutorial/static/pyramid.pngbin0 -> 12901 bytes
-rw-r--r--docs/tutorials/wiki/src/tests/tutorial/static/theme.css154
-rw-r--r--docs/tutorials/wiki/src/tests/tutorial/templates/edit.pt72
-rw-r--r--docs/tutorials/wiki/src/tests/tutorial/templates/login.pt74
-rw-r--r--docs/tutorials/wiki/src/tests/tutorial/templates/mytemplate.pt67
-rw-r--r--docs/tutorials/wiki/src/tests/tutorial/templates/view.pt72
-rw-r--r--docs/tutorials/wiki/src/tests/tutorial/tests.py65
-rw-r--r--docs/tutorials/wiki/src/tests/tutorial/views.py116
18 files changed, 848 insertions, 32 deletions
diff --git a/docs/tutorials/wiki/src/tests/CHANGES.txt b/docs/tutorials/wiki/src/tests/CHANGES.txt
new file mode 100644
index 000000000..35a34f332
--- /dev/null
+++ b/docs/tutorials/wiki/src/tests/CHANGES.txt
@@ -0,0 +1,4 @@
+0.0
+---
+
+- Initial version
diff --git a/docs/tutorials/wiki/src/tests/MANIFEST.in b/docs/tutorials/wiki/src/tests/MANIFEST.in
new file mode 100644
index 000000000..81beba1b1
--- /dev/null
+++ b/docs/tutorials/wiki/src/tests/MANIFEST.in
@@ -0,0 +1,2 @@
+include *.txt *.ini *.cfg *.rst
+recursive-include tutorial *.ico *.png *.css *.gif *.jpg *.pt *.txt *.mak *.mako *.js *.html *.xml
diff --git a/docs/tutorials/wiki/src/tests/README.txt b/docs/tutorials/wiki/src/tests/README.txt
new file mode 100644
index 000000000..dcb3605b8
--- /dev/null
+++ b/docs/tutorials/wiki/src/tests/README.txt
@@ -0,0 +1,12 @@
+tutorial README
+==================
+
+Getting Started
+---------------
+
+- cd <directory containing this file>
+
+- $VENV/bin/pip install -e .
+
+- $VENV/bin/pserve development.ini
+
diff --git a/docs/tutorials/wiki/src/tests/development.ini b/docs/tutorials/wiki/src/tests/development.ini
new file mode 100644
index 000000000..6bf4b198e
--- /dev/null
+++ b/docs/tutorials/wiki/src/tests/development.ini
@@ -0,0 +1,65 @@
+###
+# app configuration
+# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/environment.html
+###
+
+[app:main]
+use = egg:tutorial
+
+pyramid.reload_templates = true
+pyramid.debug_authorization = false
+pyramid.debug_notfound = false
+pyramid.debug_routematch = false
+pyramid.default_locale_name = en
+pyramid.includes =
+ pyramid_debugtoolbar
+ pyramid_zodbconn
+ pyramid_tm
+
+tm.attempts = 3
+zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000
+
+# By default, the toolbar only appears for clients from IP addresses
+# '127.0.0.1' and '::1'.
+# debugtoolbar.hosts = 127.0.0.1 ::1
+
+###
+# wsgi server configuration
+###
+
+[server:main]
+use = egg:waitress#main
+host = 127.0.0.1
+port = 6543
+
+###
+# logging configuration
+# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/logging.html
+###
+
+[loggers]
+keys = root, tutorial
+
+[handlers]
+keys = console
+
+[formatters]
+keys = generic
+
+[logger_root]
+level = INFO
+handlers = console
+
+[logger_tutorial]
+level = DEBUG
+handlers =
+qualname = tutorial
+
+[handler_console]
+class = StreamHandler
+args = (sys.stderr,)
+level = NOTSET
+formatter = generic
+
+[formatter_generic]
+format = %(asctime)s %(levelname)-5.5s [%(name)s:%(lineno)s][%(threadName)s] %(message)s
diff --git a/docs/tutorials/wiki/src/tests/production.ini b/docs/tutorials/wiki/src/tests/production.ini
new file mode 100644
index 000000000..4e9892e7b
--- /dev/null
+++ b/docs/tutorials/wiki/src/tests/production.ini
@@ -0,0 +1,60 @@
+###
+# app configuration
+# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/environment.html
+###
+
+[app:main]
+use = egg:tutorial
+
+pyramid.reload_templates = false
+pyramid.debug_authorization = false
+pyramid.debug_notfound = false
+pyramid.debug_routematch = false
+pyramid.default_locale_name = en
+pyramid.includes =
+ pyramid_tm
+ pyramid_zodbconn
+
+tm.attempts = 3
+zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000
+
+###
+# wsgi server configuration
+###
+
+[server:main]
+use = egg:waitress#main
+host = 0.0.0.0
+port = 6543
+
+###
+# logging configuration
+# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/logging.html
+###
+
+[loggers]
+keys = root, tutorial
+
+[handlers]
+keys = console
+
+[formatters]
+keys = generic
+
+[logger_root]
+level = WARN
+handlers = console
+
+[logger_tutorial]
+level = WARN
+handlers =
+qualname = tutorial
+
+[handler_console]
+class = StreamHandler
+args = (sys.stderr,)
+level = NOTSET
+formatter = generic
+
+[formatter_generic]
+format = %(asctime)s %(levelname)-5.5s [%(name)s:%(lineno)s][%(threadName)s] %(message)s
diff --git a/docs/tutorials/wiki/src/tests/setup.py b/docs/tutorials/wiki/src/tests/setup.py
new file mode 100644
index 000000000..beeed75c9
--- /dev/null
+++ b/docs/tutorials/wiki/src/tests/setup.py
@@ -0,0 +1,54 @@
+import os
+
+from setuptools import setup, find_packages
+
+here = os.path.abspath(os.path.dirname(__file__))
+with open(os.path.join(here, 'README.txt')) as f:
+ README = f.read()
+with open(os.path.join(here, 'CHANGES.txt')) as f:
+ CHANGES = f.read()
+
+requires = [
+ 'pyramid',
+ 'pyramid_chameleon',
+ 'pyramid_debugtoolbar',
+ 'pyramid_tm',
+ 'pyramid_zodbconn',
+ 'transaction',
+ 'ZODB3',
+ 'waitress',
+ 'docutils',
+ ]
+
+tests_require = [
+ 'WebTest >= 1.3.1', # py3 compat
+ 'pytest', # includes virtualenv
+ 'pytest-cov',
+ ]
+
+setup(name='tutorial',
+ version='0.0',
+ description='tutorial',
+ long_description=README + '\n\n' + CHANGES,
+ classifiers=[
+ "Programming Language :: Python",
+ "Framework :: Pyramid",
+ "Topic :: Internet :: WWW/HTTP",
+ "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
+ ],
+ author='',
+ author_email='',
+ url='',
+ keywords='web pylons pyramid',
+ packages=find_packages(),
+ include_package_data=True,
+ zip_safe=False,
+ extras_require={
+ 'testing': tests_require,
+ },
+ install_requires=requires,
+ entry_points="""\
+ [paste.app_factory]
+ main = tutorial:main
+ """,
+ )
diff --git a/docs/tutorials/wiki/src/tests/tutorial/__init__.py b/docs/tutorials/wiki/src/tests/tutorial/__init__.py
new file mode 100644
index 000000000..39b94abd1
--- /dev/null
+++ b/docs/tutorials/wiki/src/tests/tutorial/__init__.py
@@ -0,0 +1,27 @@
+from pyramid.config import Configurator
+from pyramid_zodbconn import get_connection
+
+from pyramid.authentication import AuthTktAuthenticationPolicy
+from pyramid.authorization import ACLAuthorizationPolicy
+
+from .models import appmaker
+from .security import groupfinder
+
+def root_factory(request):
+ conn = get_connection(request)
+ return appmaker(conn.root())
+
+
+def main(global_config, **settings):
+ """ This function returns a Pyramid WSGI application.
+ """
+ authn_policy = AuthTktAuthenticationPolicy(
+ 'sosecret', callback=groupfinder, hashalg='sha512')
+ authz_policy = ACLAuthorizationPolicy()
+ config = Configurator(root_factory=root_factory, settings=settings)
+ config.set_authentication_policy(authn_policy)
+ config.set_authorization_policy(authz_policy)
+ config.include('pyramid_chameleon')
+ config.add_static_view('static', 'static', cache_max_age=3600)
+ config.scan()
+ return config.make_wsgi_app()
diff --git a/docs/tutorials/wiki/src/tests/tutorial/models.py b/docs/tutorials/wiki/src/tests/tutorial/models.py
new file mode 100644
index 000000000..38fdd2dfc
--- /dev/null
+++ b/docs/tutorials/wiki/src/tests/tutorial/models.py
@@ -0,0 +1,29 @@
+from persistent import Persistent
+from persistent.mapping import PersistentMapping
+
+from pyramid.security import (
+ Allow,
+ Everyone,
+ )
+
+class Wiki(PersistentMapping):
+ __name__ = None
+ __parent__ = None
+ __acl__ = [ (Allow, Everyone, 'view'),
+ (Allow, 'group:editors', 'edit') ]
+
+class Page(Persistent):
+ def __init__(self, data):
+ self.data = data
+
+def appmaker(zodb_root):
+ if 'app_root' not in zodb_root:
+ app_root = Wiki()
+ frontpage = Page('This is the front page')
+ app_root['FrontPage'] = frontpage
+ frontpage.__name__ = 'FrontPage'
+ frontpage.__parent__ = app_root
+ zodb_root['app_root'] = app_root
+ import transaction
+ transaction.commit()
+ return zodb_root['app_root']
diff --git a/docs/tutorials/wiki/src/tests/tutorial/security.py b/docs/tutorials/wiki/src/tests/tutorial/security.py
new file mode 100644
index 000000000..d88c9c71f
--- /dev/null
+++ b/docs/tutorials/wiki/src/tests/tutorial/security.py
@@ -0,0 +1,7 @@
+USERS = {'editor':'editor',
+ 'viewer':'viewer'}
+GROUPS = {'editor':['group:editors']}
+
+def groupfinder(userid, request):
+ if userid in USERS:
+ return GROUPS.get(userid, [])
diff --git a/docs/tutorials/wiki/src/tests/tutorial/static/pyramid-16x16.png b/docs/tutorials/wiki/src/tests/tutorial/static/pyramid-16x16.png
new file mode 100644
index 000000000..979203112
--- /dev/null
+++ b/docs/tutorials/wiki/src/tests/tutorial/static/pyramid-16x16.png
Binary files differ
diff --git a/docs/tutorials/wiki/src/tests/tutorial/static/pyramid.png b/docs/tutorials/wiki/src/tests/tutorial/static/pyramid.png
new file mode 100644
index 000000000..4ab837be9
--- /dev/null
+++ b/docs/tutorials/wiki/src/tests/tutorial/static/pyramid.png
Binary files differ
diff --git a/docs/tutorials/wiki/src/tests/tutorial/static/theme.css b/docs/tutorials/wiki/src/tests/tutorial/static/theme.css
new file mode 100644
index 000000000..0f4b1a4d4
--- /dev/null
+++ b/docs/tutorials/wiki/src/tests/tutorial/static/theme.css
@@ -0,0 +1,154 @@
+@import url(//fonts.googleapis.com/css?family=Open+Sans:300,400,600,700);
+body {
+ font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-weight: 300;
+ color: #ffffff;
+ background: #bc2131;
+}
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+ font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-weight: 300;
+}
+p {
+ font-weight: 300;
+}
+.font-normal {
+ font-weight: 400;
+}
+.font-semi-bold {
+ font-weight: 600;
+}
+.font-bold {
+ font-weight: 700;
+}
+.starter-template {
+ margin-top: 250px;
+}
+.starter-template .content {
+ margin-left: 10px;
+}
+.starter-template .content h1 {
+ margin-top: 10px;
+ font-size: 60px;
+}
+.starter-template .content h1 .smaller {
+ font-size: 40px;
+ color: #f2b7bd;
+}
+.starter-template .content .lead {
+ font-size: 25px;
+ color: #f2b7bd;
+}
+.starter-template .content .lead .font-normal {
+ color: #ffffff;
+}
+.starter-template .links {
+ float: right;
+ right: 0;
+ margin-top: 125px;
+}
+.starter-template .links ul {
+ display: block;
+ padding: 0;
+ margin: 0;
+}
+.starter-template .links ul li {
+ list-style: none;
+ display: inline;
+ margin: 0 10px;
+}
+.starter-template .links ul li:first-child {
+ margin-left: 0;
+}
+.starter-template .links ul li:last-child {
+ margin-right: 0;
+}
+.starter-template .links ul li.current-version {
+ color: #f2b7bd;
+ font-weight: 400;
+}
+.starter-template .links ul li a, a {
+ color: #f2b7bd;
+ text-decoration: underline;
+}
+.starter-template .links ul li a:hover, a:hover {
+ color: #ffffff;
+ text-decoration: underline;
+}
+.starter-template .links ul li .icon-muted {
+ color: #eb8b95;
+ margin-right: 5px;
+}
+.starter-template .links ul li:hover .icon-muted {
+ color: #ffffff;
+}
+.starter-template .copyright {
+ margin-top: 10px;
+ font-size: 0.9em;
+ color: #f2b7bd;
+ text-transform: lowercase;
+ float: right;
+ right: 0;
+}
+@media (max-width: 1199px) {
+ .starter-template .content h1 {
+ font-size: 45px;
+ }
+ .starter-template .content h1 .smaller {
+ font-size: 30px;
+ }
+ .starter-template .content .lead {
+ font-size: 20px;
+ }
+}
+@media (max-width: 991px) {
+ .starter-template {
+ margin-top: 0;
+ }
+ .starter-template .logo {
+ margin: 40px auto;
+ }
+ .starter-template .content {
+ margin-left: 0;
+ text-align: center;
+ }
+ .starter-template .content h1 {
+ margin-bottom: 20px;
+ }
+ .starter-template .links {
+ float: none;
+ text-align: center;
+ margin-top: 60px;
+ }
+ .starter-template .copyright {
+ float: none;
+ text-align: center;
+ }
+}
+@media (max-width: 767px) {
+ .starter-template .content h1 .smaller {
+ font-size: 25px;
+ display: block;
+ }
+ .starter-template .content .lead {
+ font-size: 16px;
+ }
+ .starter-template .links {
+ margin-top: 40px;
+ }
+ .starter-template .links ul li {
+ display: block;
+ margin: 0;
+ }
+ .starter-template .links ul li .icon-muted {
+ display: none;
+ }
+ .starter-template .copyright {
+ margin-top: 20px;
+ }
+}
diff --git a/docs/tutorials/wiki/src/tests/tutorial/templates/edit.pt b/docs/tutorials/wiki/src/tests/tutorial/templates/edit.pt
new file mode 100644
index 000000000..823fa8972
--- /dev/null
+++ b/docs/tutorials/wiki/src/tests/tutorial/templates/edit.pt
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<html lang="${request.locale_name}">
+ <head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="pyramid web application">
+ <meta name="author" content="Pylons Project">
+ <link rel="shortcut icon" href="${request.static_url('tutorial:static/pyramid-16x16.png')}">
+
+ <title>${page.__name__} - Pyramid tutorial wiki (based on
+ TurboGears 20-Minute Wiki)</title>
+
+ <!-- Bootstrap core CSS -->
+ <link href="//oss.maxcdn.com/libs/twitter-bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
+
+ <!-- Custom styles for this scaffold -->
+ <link href="${request.static_url('tutorial:static/theme.css')}" rel="stylesheet">
+
+ <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
+ <!--[if lt IE 9]>
+ <script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
+ <script src="//oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
+ <![endif]-->
+ </head>
+ <body>
+
+ <div class="starter-template">
+ <div class="container">
+ <div class="row">
+ <div class="col-md-2">
+ <img class="logo img-responsive" src="${request.static_url('tutorial:static/pyramid.png')}" alt="pyramid web framework">
+ </div>
+ <div class="col-md-10">
+ <div class="content">
+ <p tal:condition="logged_in" class="pull-right">
+ <a href="${request.application_url}/logout">Logout</a>
+ </p>
+ <p>
+ Editing <strong><span tal:replace="page.__name__">
+ Page Name Goes Here</span></strong>
+ </p>
+ <p>You can return to the
+ <a href="${request.application_url}">FrontPage</a>.
+ </p>
+ <form action="${save_url}" method="post">
+ <div class="form-group">
+ <textarea class="form-control" name="body" tal:content="page.data" rows="10" cols="60"></textarea>
+ </div>
+ <div class="form-group">
+ <button type="submit" name="form.submitted" value="Save" class="btn btn-default">Save</button>
+ </div>
+ </form>
+ </div>
+ </div>
+ </div>
+ <div class="row">
+ <div class="copyright">
+ Copyright &copy; Pylons Project
+ </div>
+ </div>
+ </div>
+ </div>
+
+
+ <!-- Bootstrap core JavaScript
+ ================================================== -->
+ <!-- Placed at the end of the document so the pages load faster -->
+ <script src="//oss.maxcdn.com/libs/jquery/1.10.2/jquery.min.js"></script>
+ <script src="//oss.maxcdn.com/libs/twitter-bootstrap/3.0.3/js/bootstrap.min.js"></script>
+ </body>
+</html>
diff --git a/docs/tutorials/wiki/src/tests/tutorial/templates/login.pt b/docs/tutorials/wiki/src/tests/tutorial/templates/login.pt
new file mode 100644
index 000000000..4a938e9bb
--- /dev/null
+++ b/docs/tutorials/wiki/src/tests/tutorial/templates/login.pt
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html lang="${request.locale_name}">
+ <head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="pyramid web application">
+ <meta name="author" content="Pylons Project">
+ <link rel="shortcut icon" href="${request.static_url('tutorial:static/pyramid-16x16.png')}">
+
+ <title>Login - Pyramid tutorial wiki (based on
+ TurboGears 20-Minute Wiki)</title>
+
+ <!-- Bootstrap core CSS -->
+ <link href="//oss.maxcdn.com/libs/twitter-bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
+
+ <!-- Custom styles for this scaffold -->
+ <link href="${request.static_url('tutorial:static/theme.css')}" rel="stylesheet">
+
+ <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
+ <!--[if lt IE 9]>
+ <script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
+ <script src="//oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
+ <![endif]-->
+ </head>
+ <body>
+
+ <div class="starter-template">
+ <div class="container">
+ <div class="row">
+ <div class="col-md-2">
+ <img class="logo img-responsive" src="${request.static_url('tutorial:static/pyramid.png')}" alt="pyramid web framework">
+ </div>
+ <div class="col-md-10">
+ <div class="content">
+ <p>
+ <strong>
+ Login
+ </strong><br>
+ <span tal:replace="message"></span>
+ </p>
+ <form action="${url}" method="post">
+ <input type="hidden" name="came_from" value="${came_from}">
+ <div class="form-group">
+ <label for="login">Username</label>
+ <input type="text" name="login" value="${login}">
+ </div>
+ <div class="form-group">
+ <label for="password">Password</label>
+ <input type="password" name="password" value="${password}">
+ </div>
+ <div class="form-group">
+ <button type="submit" name="form.submitted" value="Log In" class="btn btn-default">Log In</button>
+ </div>
+ </form>
+ </div>
+ </div>
+ </div>
+ <div class="row">
+ <div class="copyright">
+ Copyright &copy; Pylons Project
+ </div>
+ </div>
+ </div>
+ </div>
+
+
+ <!-- Bootstrap core JavaScript
+ ================================================== -->
+ <!-- Placed at the end of the document so the pages load faster -->
+ <script src="//oss.maxcdn.com/libs/jquery/1.10.2/jquery.min.js"></script>
+ <script src="//oss.maxcdn.com/libs/twitter-bootstrap/3.0.3/js/bootstrap.min.js"></script>
+ </body>
+</html>
diff --git a/docs/tutorials/wiki/src/tests/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki/src/tests/tutorial/templates/mytemplate.pt
new file mode 100644
index 000000000..f8cbe2e2c
--- /dev/null
+++ b/docs/tutorials/wiki/src/tests/tutorial/templates/mytemplate.pt
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html lang="${request.locale_name}">
+ <head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="pyramid web application">
+ <meta name="author" content="Pylons Project">
+ <link rel="shortcut icon" href="${request.static_url('tutorial:static/pyramid-16x16.png')}">
+
+ <title>ZODB Scaffold for The Pyramid Web Framework</title>
+
+ <!-- Bootstrap core CSS -->
+ <link href="//oss.maxcdn.com/libs/twitter-bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
+
+ <!-- Custom styles for this scaffold -->
+ <link href="${request.static_url('tutorial:static/theme.css')}" rel="stylesheet">
+
+ <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
+ <!--[if lt IE 9]>
+ <script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
+ <script src="//oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
+ <![endif]-->
+ </head>
+
+ <body>
+
+ <div class="starter-template">
+ <div class="container">
+ <div class="row">
+ <div class="col-md-2">
+ <img class="logo img-responsive" src="${request.static_url('tutorial:static/pyramid.png')}" alt="pyramid web framework">
+ </div>
+ <div class="col-md-10">
+ <div class="content">
+ <h1><span class="font-semi-bold">Pyramid</span> <span class="smaller">ZODB scaffold</span></h1>
+ <p class="lead">Welcome to <span class="font-normal">${project}</span>, an&nbsp;application generated&nbsp;by<br>the <span class="font-normal">Pyramid Web Framework 1.7</span>.</p>
+ </div>
+ </div>
+ </div>
+ <div class="row">
+ <div class="links">
+ <ul>
+ <li class="current-version">Generated by v1.7</li>
+ <li><i class="glyphicon glyphicon-bookmark icon-muted"></i><a href="http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/">Docs</a></li>
+ <li><i class="glyphicon glyphicon-cog icon-muted"></i><a href="https://github.com/Pylons/pyramid">Github Project</a></li>
+ <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="irc://irc.freenode.net#pyramid">IRC Channel</a></li>
+ <li><i class="glyphicon glyphicon-home icon-muted"></i><a href="http://pylonsproject.org">Pylons Project</a></li>
+ </ul>
+ </div>
+ </div>
+ <div class="row">
+ <div class="copyright">
+ Copyright &copy; Pylons Project
+ </div>
+ </div>
+ </div>
+ </div>
+
+
+ <!-- Bootstrap core JavaScript
+ ================================================== -->
+ <!-- Placed at the end of the document so the pages load faster -->
+ <script src="//oss.maxcdn.com/libs/jquery/1.10.2/jquery.min.js"></script>
+ <script src="//oss.maxcdn.com/libs/twitter-bootstrap/3.0.3/js/bootstrap.min.js"></script>
+ </body>
+</html>
diff --git a/docs/tutorials/wiki/src/tests/tutorial/templates/view.pt b/docs/tutorials/wiki/src/tests/tutorial/templates/view.pt
new file mode 100644
index 000000000..fa35d758d
--- /dev/null
+++ b/docs/tutorials/wiki/src/tests/tutorial/templates/view.pt
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<html lang="${request.locale_name}">
+ <head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="pyramid web application">
+ <meta name="author" content="Pylons Project">
+ <link rel="shortcut icon" href="${request.static_url('tutorial:static/pyramid-16x16.png')}">
+
+ <title>${page.__name__} - Pyramid tutorial wiki (based on
+ TurboGears 20-Minute Wiki)</title>
+
+ <!-- Bootstrap core CSS -->
+ <link href="//oss.maxcdn.com/libs/twitter-bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
+
+ <!-- Custom styles for this scaffold -->
+ <link href="${request.static_url('tutorial:static/theme.css')}" rel="stylesheet">
+
+ <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
+ <!--[if lt IE 9]>
+ <script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
+ <script src="//oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
+ <![endif]-->
+ </head>
+ <body>
+
+ <div class="starter-template">
+ <div class="container">
+ <div class="row">
+ <div class="col-md-2">
+ <img class="logo img-responsive" src="${request.static_url('tutorial:static/pyramid.png')}" alt="pyramid web framework">
+ </div>
+ <div class="col-md-10">
+ <div class="content">
+ <p tal:condition="logged_in" class="pull-right">
+ <a href="${request.application_url}/logout">Logout</a>
+ </p>
+ <div tal:replace="structure content">
+ Page text goes here.
+ </div>
+ <p>
+ <a tal:attributes="href edit_url" href="">
+ Edit this page
+ </a>
+ </p>
+ <p>
+ Viewing <strong><span tal:replace="page.__name__">
+ Page Name Goes Here</span></strong>
+ </p>
+ <p>You can return to the
+ <a href="${request.application_url}">FrontPage</a>.
+ </p>
+ </div>
+ </div>
+ </div>
+ <div class="row">
+ <div class="copyright">
+ Copyright &copy; Pylons Project
+ </div>
+ </div>
+ </div>
+ </div>
+
+
+ <!-- Bootstrap core JavaScript
+ ================================================== -->
+ <!-- Placed at the end of the document so the pages load faster -->
+ <script src="//oss.maxcdn.com/libs/jquery/1.10.2/jquery.min.js"></script>
+ <script src="//oss.maxcdn.com/libs/twitter-bootstrap/3.0.3/js/bootstrap.min.js"></script>
+ </body>
+</html>
diff --git a/docs/tutorials/wiki/src/tests/tutorial/tests.py b/docs/tutorials/wiki/src/tests/tutorial/tests.py
index 0ce5ea718..04beaea44 100644
--- a/docs/tutorials/wiki/src/tests/tutorial/tests.py
+++ b/docs/tutorials/wiki/src/tests/tutorial/tests.py
@@ -5,7 +5,7 @@ from pyramid import testing
class PageModelTests(unittest.TestCase):
def _getTargetClass(self):
- from tutorial.models import Page
+ from .models import Page
return Page
def _makeOne(self, data=u'some data'):
@@ -18,7 +18,7 @@ class PageModelTests(unittest.TestCase):
class WikiModelTests(unittest.TestCase):
def _getTargetClass(self):
- from tutorial.models import Wiki
+ from .models import Wiki
return Wiki
def _makeOne(self):
@@ -30,8 +30,9 @@ class WikiModelTests(unittest.TestCase):
self.assertEqual(wiki.__name__, None)
class AppmakerTests(unittest.TestCase):
+
def _callFUT(self, zodb_root):
- from tutorial.models import appmaker
+ from .models import appmaker
return appmaker(zodb_root)
def test_it(self):
@@ -42,7 +43,7 @@ class AppmakerTests(unittest.TestCase):
class ViewWikiTests(unittest.TestCase):
def test_it(self):
- from tutorial.views import view_wiki
+ from .views import view_wiki
context = testing.DummyResource()
request = testing.DummyRequest()
response = view_wiki(context, request)
@@ -50,7 +51,7 @@ class ViewWikiTests(unittest.TestCase):
class ViewPageTests(unittest.TestCase):
def _callFUT(self, context, request):
- from tutorial.views import view_page
+ from .views import view_page
return view_page(context, request)
def test_it(self):
@@ -76,11 +77,10 @@ class ViewPageTests(unittest.TestCase):
class AddPageTests(unittest.TestCase):
def _callFUT(self, context, request):
- from tutorial.views import add_page
+ from .views import add_page
return add_page(context, request)
def test_it_notsubmitted(self):
- from pyramid.url import resource_url
context = testing.DummyResource()
request = testing.DummyRequest()
request.subpath = ['AnotherPage']
@@ -88,7 +88,7 @@ class AddPageTests(unittest.TestCase):
self.assertEqual(info['page'].data,'')
self.assertEqual(
info['save_url'],
- resource_url(context, request, 'add_page', 'AnotherPage'))
+ request.resource_url(context, 'add_page', 'AnotherPage'))
def test_it_submitted(self):
context = testing.DummyResource()
@@ -103,17 +103,16 @@ class AddPageTests(unittest.TestCase):
class EditPageTests(unittest.TestCase):
def _callFUT(self, context, request):
- from tutorial.views import edit_page
+ from .views import edit_page
return edit_page(context, request)
def test_it_notsubmitted(self):
- from pyramid.url import resource_url
context = testing.DummyResource()
request = testing.DummyRequest()
info = self._callFUT(context, request)
self.assertEqual(info['page'], context)
self.assertEqual(info['save_url'],
- resource_url(context, request, 'edit_page'))
+ request.resource_url(context, 'edit_page'))
def test_it_submitted(self):
context = testing.DummyResource()
@@ -135,18 +134,16 @@ class FunctionalTests(unittest.TestCase):
def setUp(self):
import tempfile
import os.path
- from tutorial import main
+ from . import main
self.tmpdir = tempfile.mkdtemp()
dbpath = os.path.join( self.tmpdir, 'test.db')
- from repoze.zodbconn.uri import db_from_uri
- db = db_from_uri('file://' + dbpath)
- settings = { 'zodb_uri' : None }
+ uri = 'file://' + dbpath
+ settings = { 'zodbconn.uri' : uri ,
+ 'pyramid.includes': ['pyramid_zodbconn', 'pyramid_tm'] }
app = main({}, **settings)
- from repoze.zodbconn.connector import Connector
- app = Connector(app, db)
- self.db = db
+ self.db = app.registry._zodb_databases['']
from webtest import TestApp
self.testapp = TestApp(app)
@@ -157,64 +154,68 @@ class FunctionalTests(unittest.TestCase):
def test_root(self):
res = self.testapp.get('/', status=302)
- self.assertTrue(not res.body)
+ self.assertEqual(res.location, 'http://localhost/FrontPage')
def test_FrontPage(self):
res = self.testapp.get('/FrontPage', status=200)
- self.assertTrue('FrontPage' in res.body)
+ self.assertTrue(b'FrontPage' in res.body)
def test_unexisting_page(self):
res = self.testapp.get('/SomePage', status=404)
- self.assertTrue('Not Found' in res.body)
+ self.assertTrue(b'Not Found' in res.body)
+
+ def test_referrer_is_login(self):
+ res = self.testapp.get('/login', status=200)
+ self.assertTrue(b'name="came_from" value="/"' in res.body)
def test_successful_log_in(self):
res = self.testapp.get( self.viewer_login, status=302)
- self.assertTrue(res.location == 'FrontPage')
+ self.assertEqual(res.location, 'http://localhost/FrontPage')
def test_failed_log_in(self):
res = self.testapp.get( self.viewer_wrong_login, status=200)
- self.assertTrue('login' in res.body)
+ self.assertTrue(b'login' in res.body)
def test_logout_link_present_when_logged_in(self):
res = self.testapp.get( self.viewer_login, status=302)
res = self.testapp.get('/FrontPage', status=200)
- self.assertTrue('Logout' in res.body)
+ self.assertTrue(b'Logout' in res.body)
def test_logout_link_not_present_after_logged_out(self):
res = self.testapp.get( self.viewer_login, status=302)
res = self.testapp.get('/FrontPage', status=200)
res = self.testapp.get('/logout', status=302)
- self.assertTrue('Logout' not in res.body)
+ self.assertTrue(b'Logout' not in res.body)
def test_anonymous_user_cannot_edit(self):
res = self.testapp.get('/FrontPage/edit_page', status=200)
- self.assertTrue('Login' in res.body)
+ self.assertTrue(b'Login' in res.body)
def test_anonymous_user_cannot_add(self):
res = self.testapp.get('/add_page/NewPage', status=200)
- self.assertTrue('Login' in res.body)
+ self.assertTrue(b'Login' in res.body)
def test_viewer_user_cannot_edit(self):
res = self.testapp.get( self.viewer_login, status=302)
res = self.testapp.get('/FrontPage/edit_page', status=200)
- self.assertTrue('Login' in res.body)
+ self.assertTrue(b'Login' in res.body)
def test_viewer_user_cannot_add(self):
res = self.testapp.get( self.viewer_login, status=302)
res = self.testapp.get('/add_page/NewPage', status=200)
- self.assertTrue('Login' in res.body)
+ self.assertTrue(b'Login' in res.body)
def test_editors_member_user_can_edit(self):
res = self.testapp.get( self.editor_login, status=302)
res = self.testapp.get('/FrontPage/edit_page', status=200)
- self.assertTrue('Editing' in res.body)
+ self.assertTrue(b'Editing' in res.body)
def test_editors_member_user_can_add(self):
res = self.testapp.get( self.editor_login, status=302)
res = self.testapp.get('/add_page/NewPage', status=200)
- self.assertTrue('Editing' in res.body)
+ self.assertTrue(b'Editing' in res.body)
def test_editors_member_user_can_view(self):
res = self.testapp.get( self.editor_login, status=302)
res = self.testapp.get('/FrontPage', status=200)
- self.assertTrue('FrontPage' in res.body)
+ self.assertTrue(b'FrontPage' in res.body)
diff --git a/docs/tutorials/wiki/src/tests/tutorial/views.py b/docs/tutorials/wiki/src/tests/tutorial/views.py
new file mode 100644
index 000000000..c271d2cc1
--- /dev/null
+++ b/docs/tutorials/wiki/src/tests/tutorial/views.py
@@ -0,0 +1,116 @@
+from docutils.core import publish_parts
+import re
+
+from pyramid.httpexceptions import HTTPFound
+
+from pyramid.view import (
+ view_config,
+ forbidden_view_config,
+ )
+
+from pyramid.security import (
+ remember,
+ forget,
+ )
+
+
+from .security import USERS
+from .models import Page
+
+# regular expression used to find WikiWords
+wikiwords = re.compile(r"\b([A-Z]\w+[A-Z]+\w+)")
+
+@view_config(context='.models.Wiki',
+ permission='view')
+def view_wiki(context, request):
+ return HTTPFound(location=request.resource_url(context, 'FrontPage'))
+
+@view_config(context='.models.Page', renderer='templates/view.pt',
+ permission='view')
+def view_page(context, request):
+ wiki = context.__parent__
+
+ def check(match):
+ word = match.group(1)
+ if word in wiki:
+ page = wiki[word]
+ view_url = request.resource_url(page)
+ return '<a href="%s">%s</a>' % (view_url, word)
+ else:
+ add_url = request.application_url + '/add_page/' + word
+ return '<a href="%s">%s</a>' % (add_url, word)
+
+ content = publish_parts(context.data, writer_name='html')['html_body']
+ content = wikiwords.sub(check, content)
+ edit_url = request.resource_url(context, 'edit_page')
+
+ return dict(page=context, content=content, edit_url=edit_url,
+ logged_in=request.authenticated_userid)
+
+@view_config(name='add_page', context='.models.Wiki',
+ renderer='templates/edit.pt',
+ permission='edit')
+def add_page(context, request):
+ pagename = request.subpath[0]
+ if 'form.submitted' in request.params:
+ body = request.params['body']
+ page = Page(body)
+ page.__name__ = pagename
+ page.__parent__ = context
+ context[pagename] = page
+ return HTTPFound(location=request.resource_url(page))
+ save_url = request.resource_url(context, 'add_page', pagename)
+ page = Page('')
+ page.__name__ = pagename
+ page.__parent__ = context
+
+ return dict(page=page, save_url=save_url,
+ logged_in=request.authenticated_userid)
+
+@view_config(name='edit_page', context='.models.Page',
+ renderer='templates/edit.pt',
+ permission='edit')
+def edit_page(context, request):
+ if 'form.submitted' in request.params:
+ context.data = request.params['body']
+ return HTTPFound(location=request.resource_url(context))
+
+ return dict(page=context,
+ save_url=request.resource_url(context, 'edit_page'),
+ logged_in=request.authenticated_userid)
+
+@view_config(context='.models.Wiki', name='login',
+ renderer='templates/login.pt')
+@forbidden_view_config(renderer='templates/login.pt')
+def login(request):
+ login_url = request.resource_url(request.context, '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(context='.models.Wiki', name='logout')
+def logout(request):
+ headers = forget(request)
+ return HTTPFound(location=request.resource_url(request.context),
+ headers=headers)