summaryrefslogtreecommitdiff
path: root/docs/tutorials
diff options
context:
space:
mode:
authorSteve Piercy <web@stevepiercy.com>2016-04-09 01:16:42 -0700
committerSteve Piercy <web@stevepiercy.com>2016-04-09 01:16:42 -0700
commit1663cdeb0ec3fd40f879ae46f94d412fa4cf6cef (patch)
tree30db998ae4753d30cbdc4750ad0649acd85bddc5 /docs/tutorials
parentd2ba24e8ac0c8e2b3bc807bf27f56c3f5d52131b (diff)
parent458d513ba5ffd054323be1da9306ad0d37d0c10f (diff)
downloadpyramid-1663cdeb0ec3fd40f879ae46f94d412fa4cf6cef.tar.gz
pyramid-1663cdeb0ec3fd40f879ae46f94d412fa4cf6cef.tar.bz2
pyramid-1663cdeb0ec3fd40f879ae46f94d412fa4cf6cef.zip
Merge pull request #2442 from stevepiercy/docs/easy-install-to-pip.2104
rough draft for wiki2, replace setup.py with pip. See #2104.
Diffstat (limited to 'docs/tutorials')
-rw-r--r--docs/tutorials/wiki2/installation.rst193
-rw-r--r--docs/tutorials/wiki2/src/installation/CHANGES.txt4
-rw-r--r--docs/tutorials/wiki2/src/installation/MANIFEST.in2
-rw-r--r--docs/tutorials/wiki2/src/installation/README.txt14
-rw-r--r--docs/tutorials/wiki2/src/installation/development.ini71
-rw-r--r--docs/tutorials/wiki2/src/installation/production.ini60
-rw-r--r--docs/tutorials/wiki2/src/installation/setup.py55
-rw-r--r--docs/tutorials/wiki2/src/installation/tutorial/__init__.py12
-rw-r--r--docs/tutorials/wiki2/src/installation/tutorial/models/__init__.py73
-rw-r--r--docs/tutorials/wiki2/src/installation/tutorial/models/meta.py16
-rw-r--r--docs/tutorials/wiki2/src/installation/tutorial/models/mymodel.py18
-rw-r--r--docs/tutorials/wiki2/src/installation/tutorial/routes.py3
-rw-r--r--docs/tutorials/wiki2/src/installation/tutorial/scripts/__init__.py1
-rw-r--r--docs/tutorials/wiki2/src/installation/tutorial/scripts/initializedb.py45
-rw-r--r--docs/tutorials/wiki2/src/installation/tutorial/static/pyramid-16x16.pngbin0 -> 1319 bytes
-rw-r--r--docs/tutorials/wiki2/src/installation/tutorial/static/pyramid.pngbin0 -> 12901 bytes
-rw-r--r--docs/tutorials/wiki2/src/installation/tutorial/static/theme.css154
-rw-r--r--docs/tutorials/wiki2/src/installation/tutorial/static/theme.min.css1
-rw-r--r--docs/tutorials/wiki2/src/installation/tutorial/templates/404.jinja28
-rw-r--r--docs/tutorials/wiki2/src/installation/tutorial/templates/layout.jinja266
-rw-r--r--docs/tutorials/wiki2/src/installation/tutorial/templates/mytemplate.jinja28
-rw-r--r--docs/tutorials/wiki2/src/installation/tutorial/tests.py65
-rw-r--r--docs/tutorials/wiki2/src/installation/tutorial/views/__init__.py0
-rw-r--r--docs/tutorials/wiki2/src/installation/tutorial/views/default.py33
-rw-r--r--docs/tutorials/wiki2/src/installation/tutorial/views/notfound.py7
25 files changed, 826 insertions, 83 deletions
diff --git a/docs/tutorials/wiki2/installation.rst b/docs/tutorials/wiki2/installation.rst
index b263ccbd9..a592029cd 100644
--- a/docs/tutorials/wiki2/installation.rst
+++ b/docs/tutorials/wiki2/installation.rst
@@ -72,8 +72,8 @@ Python 3.5:
c:\> c:\Python35\Scripts\virtualenv %VENV%
-Upgrade pip in the virtual environment
---------------------------------------
+Upgrade ``pip`` in the virtual environment
+------------------------------------------
On UNIX
^^^^^^^
@@ -187,16 +187,15 @@ On Windows
and the project into directories that do not contain spaces in their paths.
-
.. _installing_project_in_dev_mode:
Installing the project in development mode
------------------------------------------
In order to do development on the project easily, you must "register" the
-project as a development egg in your workspace using the ``setup.py develop``
+project as a development egg in your workspace using the ``pip install -e .``
command. In order to do so, change directory to the ``tutorial`` directory that
-you created in :ref:`sql_making_a_project`, and run the ``setup.py develop``
+you created in :ref:`sql_making_a_project`, and run the ``pip install -e .``
command using the virtualenv Python interpreter.
On UNIX
@@ -215,106 +214,139 @@ On Windows
c:\pyramidtut> cd tutorial
c:\pyramidtut\tutorial> %VENV%\Scripts\pip install -e .
-The console will show ``setup.py`` checking for packages and installing missing
-packages. Success executing this command will show a line like the following::
+The console will show ``pip`` checking for packages and installing missing
+packages. Success executing this command will show a line like the following:
- Finished processing dependencies for tutorial==0.0
+.. code-block:: bash
-.. _sql_running_tests:
+ Successfully installed Chameleon-2.24 Mako-1.0.4 MarkupSafe-0.23 \
+ Pygments-2.1.3 SQLAlchemy-1.0.12 pyramid-chameleon-0.3 \
+ pyramid-debugtoolbar-2.4.2 pyramid-mako-1.0.2 pyramid-tm-0.12.1 \
+ transaction-1.4.4 tutorial waitress-0.8.10 zope.sqlalchemy-0.7.6
-Run the tests
--------------
-After you've installed the project in development mode, you may run the tests
-for the project.
+.. _install-testing-requirements:
+
+Install testing requirements
+----------------------------
+
+In order to run tests, we need to install the testing requirements. This is
+done through our project's ``setup.py`` file, in the ``testing_extras`` and
+``extras_requires`` stanzas, and by issuing the command below for your
+operating system.
+
+.. literalinclude:: src/installation/setup.py
+ :language: python
+ :linenos:
+ :lineno-start: 22
+ :lines: 22-26
+
+.. literalinclude:: src/installation/setup.py
+ :language: python
+ :linenos:
+ :lineno-start: 45
+ :lines: 45-47
On UNIX
^^^^^^^
.. code-block:: bash
- $ $VENV/bin/python setup.py test -q
-
-.. py.test? See https://github.com/Pylons/pyramid/issues/2104#issuecomment-155852046
+ $ $VENV/bin/pip install -e ".[testing]"
On Windows
^^^^^^^^^^
.. code-block:: ps1con
- c:\pyramidtut\tutorial> %VENV%\Scripts\python setup.py test -q
-
-.. py.test? See https://github.com/Pylons/pyramid/issues/2104#issuecomment-155852046
+ c:\pyramidtut\tutorial> %VENV%\Scripts\pip install -e ".[testing]"
-For a successful test run, you should see output that ends like this::
-
- ..
- ----------------------------------------------------------------------
- Ran 2 tests in 0.053s
- OK
-
-Expose test coverage information
---------------------------------
+.. _sql_running_tests:
-You can run the ``nosetests`` command to see test coverage information. This
-runs the tests in the same way that ``setup.py test`` does, but provides
-additional "coverage" information, exposing which lines of your project are
-covered by the tests.
+Run the tests
+-------------
-To get this functionality working, we'll need to install the ``nose`` and
-``coverage`` packages into our ``virtualenv``:
+After you've installed the project in development mode as well as the testing
+requirements, you may run the tests for the project.
On UNIX
^^^^^^^
.. code-block:: bash
- $ $VENV/bin/easy_install nose coverage
+ $ $VENV/bin/py.test tutorial/tests.py -q
On Windows
^^^^^^^^^^
.. code-block:: ps1con
- c:\pyramidtut\tutorial> %VENV%\Scripts\easy_install nose coverage
+ c:\pyramidtut\tutorial> %VENV%\Scripts\py.test tutorial\tests.py -q
+
+For a successful test run, you should see output that ends like this:
+
+.. code-block:: bash
+
+ ..
+ 2 passed in 0.44 seconds
+
+
+Expose test coverage information
+--------------------------------
+
+You can run the ``py.test`` command to see test coverage information. This
+runs the tests in the same way that ``py.test`` does, but provides additional
+"coverage" information, exposing which lines of your project are covered by the
+tests.
-Once ``nose`` and ``coverage`` are installed, we can run the tests with
-coverage.
+We've already installed the ``pytest-cov`` package into our ``virtualenv``, so
+we can run the tests with coverage.
On UNIX
^^^^^^^
.. code-block:: bash
- $ $VENV/bin/nosetests --cover-package=tutorial --cover-erase --with-coverage
+ $ $VENV/bin/py.test --cov=tutorial --cov-report=term-missing tutorial/tests.py
On Windows
^^^^^^^^^^
.. code-block:: ps1con
- c:\pyramidtut\tutorial> %VENV%\Scripts\nosetests --cover-package=tutorial \
- --cover-erase --with-coverage
+ c:\pyramidtut\tutorial> %VENV%\Scripts\py.test --cov=tutorial \
+ --cov-report=term-missing tutorial\tests.py
-If successful, you will see output something like this::
+If successful, you will see output something like this:
- ..
- Name Stmts Miss Cover Missing
- ----------------------------------------------------------
- tutorial.py 8 6 25% 7-12
- tutorial/models.py 22 0 100%
- tutorial/models/meta.py 5 0 100%
- tutorial/models/mymodel.py 8 0 100%
- tutorial/scripts.py 0 0 100%
- tutorial/views.py 0 0 100%
- tutorial/views/default.py 12 0 100%
- ----------------------------------------------------------
- TOTAL 55 6 89%
- ----------------------------------------------------------------------
- Ran 2 tests in 0.579s
-
- OK
+.. code-block:: bash
+
+ ======================== test session starts ========================
+ platform Python 3.5.1, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
+ rootdir: /Users/stevepiercy/projects/pyramidtut/tutorial, inifile:
+ plugins: cov-2.2.1
+ collected 2 items
+
+ tutorial/tests.py ..
+ ------------------ coverage: platform Python 3.5.1 ------------------
+ Name Stmts Miss Cover Missing
+ ----------------------------------------------------------------
+ tutorial/__init__.py 8 6 25% 7-12
+ tutorial/models/__init__.py 22 0 100%
+ tutorial/models/meta.py 5 0 100%
+ tutorial/models/mymodel.py 8 0 100%
+ tutorial/routes.py 3 3 0% 1-3
+ tutorial/scripts/__init__.py 0 0 100%
+ tutorial/scripts/initializedb.py 26 26 0% 1-45
+ tutorial/tests.py 39 0 100%
+ tutorial/views/__init__.py 0 0 100%
+ tutorial/views/default.py 12 0 100%
+ tutorial/views/notfound.py 4 4 0% 1-7
+ ----------------------------------------------------------------
+ TOTAL 127 39 69%
+
+ ===================== 2 passed in 0.57 seconds ======================
Our package doesn't quite have 100% test coverage.
@@ -358,15 +390,17 @@ On Windows
c:\pyramidtut\tutorial> %VENV%\Scripts\initialize_tutorial_db development.ini
-The output to your console should be something like this::
+The output to your console should be something like this:
+
+.. code-block:: bash
- 2016-02-21 23:57:41,793 INFO [sqlalchemy.engine.base.Engine:1192][MainThread] SELECT CAST('test plain returns' AS VARCHAR(60)) AS anon_1
- 2016-02-21 23:57:41,793 INFO [sqlalchemy.engine.base.Engine:1193][MainThread] ()
- 2016-02-21 23:57:41,794 INFO [sqlalchemy.engine.base.Engine:1192][MainThread] SELECT CAST('test unicode returns' AS VARCHAR(60)) AS anon_1
- 2016-02-21 23:57:41,794 INFO [sqlalchemy.engine.base.Engine:1193][MainThread] ()
- 2016-02-21 23:57:41,796 INFO [sqlalchemy.engine.base.Engine:1097][MainThread] PRAGMA table_info("models")
- 2016-02-21 23:57:41,796 INFO [sqlalchemy.engine.base.Engine:1100][MainThread] ()
- 2016-02-21 23:57:41,798 INFO [sqlalchemy.engine.base.Engine:1097][MainThread]
+ 2016-04-09 00:53:37,801 INFO [sqlalchemy.engine.base.Engine:1192][MainThread] SELECT CAST('test plain returns' AS VARCHAR(60)) AS anon_1
+ 2016-04-09 00:53:37,801 INFO [sqlalchemy.engine.base.Engine:1193][MainThread] ()
+ 2016-04-09 00:53:37,802 INFO [sqlalchemy.engine.base.Engine:1192][MainThread] SELECT CAST('test unicode returns' AS VARCHAR(60)) AS anon_1
+ 2016-04-09 00:53:37,802 INFO [sqlalchemy.engine.base.Engine:1193][MainThread] ()
+ 2016-04-09 00:53:37,802 INFO [sqlalchemy.engine.base.Engine:1097][MainThread] PRAGMA table_info("models")
+ 2016-04-09 00:53:37,803 INFO [sqlalchemy.engine.base.Engine:1100][MainThread] ()
+ 2016-04-09 00:53:37,803 INFO [sqlalchemy.engine.base.Engine:1097][MainThread]
CREATE TABLE models (
id INTEGER NOT NULL,
name TEXT,
@@ -375,15 +409,15 @@ The output to your console should be something like this::
)
- 2016-02-21 23:57:41,798 INFO [sqlalchemy.engine.base.Engine:1100][MainThread] ()
- 2016-02-21 23:57:41,798 INFO [sqlalchemy.engine.base.Engine:686][MainThread] COMMIT
- 2016-02-21 23:57:41,799 INFO [sqlalchemy.engine.base.Engine:1097][MainThread] CREATE UNIQUE INDEX my_index ON models (name)
- 2016-02-21 23:57:41,799 INFO [sqlalchemy.engine.base.Engine:1100][MainThread] ()
- 2016-02-21 23:57:41,799 INFO [sqlalchemy.engine.base.Engine:686][MainThread] COMMIT
- 2016-02-21 23:57:41,801 INFO [sqlalchemy.engine.base.Engine:646][MainThread] BEGIN (implicit)
- 2016-02-21 23:57:41,802 INFO [sqlalchemy.engine.base.Engine:1097][MainThread] INSERT INTO models (name, value) VALUES (?, ?)
- 2016-02-21 23:57:41,802 INFO [sqlalchemy.engine.base.Engine:1100][MainThread] ('one', 1)
- 2016-02-21 23:57:41,821 INFO [sqlalchemy.engine.base.Engine:686][MainThread] COMMIT
+ 2016-04-09 00:53:37,803 INFO [sqlalchemy.engine.base.Engine:1100][MainThread] ()
+ 2016-04-09 00:53:37,804 INFO [sqlalchemy.engine.base.Engine:686][MainThread] COMMIT
+ 2016-04-09 00:53:37,805 INFO [sqlalchemy.engine.base.Engine:1097][MainThread] CREATE UNIQUE INDEX my_index ON models (name)
+ 2016-04-09 00:53:37,805 INFO [sqlalchemy.engine.base.Engine:1100][MainThread] ()
+ 2016-04-09 00:53:37,806 INFO [sqlalchemy.engine.base.Engine:686][MainThread] COMMIT
+ 2016-04-09 00:53:37,807 INFO [sqlalchemy.engine.base.Engine:646][MainThread] BEGIN (implicit)
+ 2016-04-09 00:53:37,808 INFO [sqlalchemy.engine.base.Engine:1097][MainThread] INSERT INTO models (name, value) VALUES (?, ?)
+ 2016-04-09 00:53:37,808 INFO [sqlalchemy.engine.base.Engine:1100][MainThread] ('one', 1)
+ 2016-04-09 00:53:37,809 INFO [sqlalchemy.engine.base.Engine:686][MainThread] COMMIT
Success! You should now have a ``tutorial.sqlite`` file in your current
working directory. This is an SQLite database with a single table defined in it
@@ -446,16 +480,9 @@ assumptions:
- You are willing to use :term:`URL dispatch` to map URLs to code.
-- You want to use zope.sqlalchemy_, pyramid_tm_ and the transaction_ package
+- You want to use zope.sqlalchemy_, pyramid_tm_, and the transaction_ packages
to scope sessions to requests.
-- You want to use pyramid_jinja2_ to render your templates.
- Different templating engines can be used but we had to choose one to
- make the tutorial. See :ref:`available_template_system_bindings` for some
- options.
-- You want to use zope.sqlalchemy_, pyramid_tm_ and the transaction_ package to
- scope sessions to requests.
-
- You want to use pyramid_jinja2_ to render your templates. Different
templating engines can be used, but we had to choose one to make this
tutorial. See :ref:`available_template_system_bindings` for some options.
diff --git a/docs/tutorials/wiki2/src/installation/CHANGES.txt b/docs/tutorials/wiki2/src/installation/CHANGES.txt
new file mode 100644
index 000000000..35a34f332
--- /dev/null
+++ b/docs/tutorials/wiki2/src/installation/CHANGES.txt
@@ -0,0 +1,4 @@
+0.0
+---
+
+- Initial version
diff --git a/docs/tutorials/wiki2/src/installation/MANIFEST.in b/docs/tutorials/wiki2/src/installation/MANIFEST.in
new file mode 100644
index 000000000..42cd299b5
--- /dev/null
+++ b/docs/tutorials/wiki2/src/installation/MANIFEST.in
@@ -0,0 +1,2 @@
+include *.txt *.ini *.cfg *.rst
+recursive-include tutorial *.ico *.png *.css *.gif *.jpg *.jinja2 *.pt *.txt *.mak *.mako *.js *.html *.xml
diff --git a/docs/tutorials/wiki2/src/installation/README.txt b/docs/tutorials/wiki2/src/installation/README.txt
new file mode 100644
index 000000000..68f430110
--- /dev/null
+++ b/docs/tutorials/wiki2/src/installation/README.txt
@@ -0,0 +1,14 @@
+tutorial README
+==================
+
+Getting Started
+---------------
+
+- cd <directory containing this file>
+
+- $VENV/bin/python setup.py develop
+
+- $VENV/bin/initialize_tutorial_db development.ini
+
+- $VENV/bin/pserve development.ini
+
diff --git a/docs/tutorials/wiki2/src/installation/development.ini b/docs/tutorials/wiki2/src/installation/development.ini
new file mode 100644
index 000000000..22b733e10
--- /dev/null
+++ b/docs/tutorials/wiki2/src/installation/development.ini
@@ -0,0 +1,71 @@
+###
+# 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_tm
+
+sqlalchemy.url = sqlite:///%(here)s/tutorial.sqlite
+
+# 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, sqlalchemy
+
+[handlers]
+keys = console
+
+[formatters]
+keys = generic
+
+[logger_root]
+level = INFO
+handlers = console
+
+[logger_tutorial]
+level = DEBUG
+handlers =
+qualname = tutorial
+
+[logger_sqlalchemy]
+level = INFO
+handlers =
+qualname = sqlalchemy.engine
+# "level = INFO" logs SQL queries.
+# "level = DEBUG" logs SQL queries and results.
+# "level = WARN" logs neither. (Recommended for production systems.)
+
+[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/wiki2/src/installation/production.ini b/docs/tutorials/wiki2/src/installation/production.ini
new file mode 100644
index 000000000..d2ecfe22a
--- /dev/null
+++ b/docs/tutorials/wiki2/src/installation/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
+
+sqlalchemy.url = sqlite:///%(here)s/tutorial.sqlite
+
+[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, sqlalchemy
+
+[handlers]
+keys = console
+
+[formatters]
+keys = generic
+
+[logger_root]
+level = WARN
+handlers = console
+
+[logger_tutorial]
+level = WARN
+handlers =
+qualname = tutorial
+
+[logger_sqlalchemy]
+level = WARN
+handlers =
+qualname = sqlalchemy.engine
+# "level = INFO" logs SQL queries.
+# "level = DEBUG" logs SQL queries and results.
+# "level = WARN" logs neither. (Recommended for production systems.)
+
+[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/wiki2/src/installation/setup.py b/docs/tutorials/wiki2/src/installation/setup.py
new file mode 100644
index 000000000..c82c880c9
--- /dev/null
+++ b/docs/tutorials/wiki2/src/installation/setup.py
@@ -0,0 +1,55 @@
+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_jinja2',
+ 'pyramid_debugtoolbar',
+ 'pyramid_tm',
+ 'SQLAlchemy',
+ 'transaction',
+ 'zope.sqlalchemy',
+ 'waitress',
+ ]
+
+testing_extras = [
+ '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 wsgi bfg pylons pyramid',
+ packages=find_packages(),
+ include_package_data=True,
+ zip_safe=False,
+ extras_require={
+ 'testing': testing_extras,
+ },
+ install_requires=requires,
+ entry_points="""\
+ [paste.app_factory]
+ main = tutorial:main
+ [console_scripts]
+ initialize_tutorial_db = tutorial.scripts.initializedb:main
+ """,
+ )
diff --git a/docs/tutorials/wiki2/src/installation/tutorial/__init__.py b/docs/tutorials/wiki2/src/installation/tutorial/__init__.py
new file mode 100644
index 000000000..4dab44823
--- /dev/null
+++ b/docs/tutorials/wiki2/src/installation/tutorial/__init__.py
@@ -0,0 +1,12 @@
+from pyramid.config import Configurator
+
+
+def main(global_config, **settings):
+ """ This function returns a Pyramid WSGI application.
+ """
+ config = Configurator(settings=settings)
+ config.include('pyramid_jinja2')
+ config.include('.models')
+ config.include('.routes')
+ config.scan()
+ return config.make_wsgi_app()
diff --git a/docs/tutorials/wiki2/src/installation/tutorial/models/__init__.py b/docs/tutorials/wiki2/src/installation/tutorial/models/__init__.py
new file mode 100644
index 000000000..48a957ecb
--- /dev/null
+++ b/docs/tutorials/wiki2/src/installation/tutorial/models/__init__.py
@@ -0,0 +1,73 @@
+from sqlalchemy import engine_from_config
+from sqlalchemy.orm import sessionmaker
+from sqlalchemy.orm import configure_mappers
+import zope.sqlalchemy
+
+# import or define all models here to ensure they are attached to the
+# Base.metadata prior to any initialization routines
+from .mymodel import MyModel # flake8: noqa
+
+# run configure_mappers after defining all of the models to ensure
+# all relationships can be setup
+configure_mappers()
+
+
+def get_engine(settings, prefix='sqlalchemy.'):
+ return engine_from_config(settings, prefix)
+
+
+def get_session_factory(engine):
+ factory = sessionmaker()
+ factory.configure(bind=engine)
+ return factory
+
+
+def get_tm_session(session_factory, transaction_manager):
+ """
+ Get a ``sqlalchemy.orm.Session`` instance backed by a transaction.
+
+ This function will hook the session to the transaction manager which
+ will take care of committing any changes.
+
+ - When using pyramid_tm it will automatically be committed or aborted
+ depending on whether an exception is raised.
+
+ - When using scripts you should wrap the session in a manager yourself.
+ For example::
+
+ import transaction
+
+ engine = get_engine(settings)
+ session_factory = get_session_factory(engine)
+ with transaction.manager:
+ dbsession = get_tm_session(session_factory, transaction.manager)
+
+ """
+ dbsession = session_factory()
+ zope.sqlalchemy.register(
+ dbsession, transaction_manager=transaction_manager)
+ return dbsession
+
+
+def includeme(config):
+ """
+ Initialize the model for a Pyramid app.
+
+ Activate this setup using ``config.include('tutorial.models')``.
+
+ """
+ settings = config.get_settings()
+
+ # use pyramid_tm to hook the transaction lifecycle to the request
+ config.include('pyramid_tm')
+
+ session_factory = get_session_factory(get_engine(settings))
+ config.registry['dbsession_factory'] = session_factory
+
+ # make request.dbsession available for use in Pyramid
+ config.add_request_method(
+ # r.tm is the transaction manager used by pyramid_tm
+ lambda r: get_tm_session(session_factory, r.tm),
+ 'dbsession',
+ reify=True
+ )
diff --git a/docs/tutorials/wiki2/src/installation/tutorial/models/meta.py b/docs/tutorials/wiki2/src/installation/tutorial/models/meta.py
new file mode 100644
index 000000000..fc3e8f1dd
--- /dev/null
+++ b/docs/tutorials/wiki2/src/installation/tutorial/models/meta.py
@@ -0,0 +1,16 @@
+from sqlalchemy.ext.declarative import declarative_base
+from sqlalchemy.schema import MetaData
+
+# Recommended naming convention used by Alembic, as various different database
+# providers will autogenerate vastly different names making migrations more
+# difficult. See: http://alembic.readthedocs.org/en/latest/naming.html
+NAMING_CONVENTION = {
+ "ix": 'ix_%(column_0_label)s',
+ "uq": "uq_%(table_name)s_%(column_0_name)s",
+ "ck": "ck_%(table_name)s_%(constraint_name)s",
+ "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
+ "pk": "pk_%(table_name)s"
+}
+
+metadata = MetaData(naming_convention=NAMING_CONVENTION)
+Base = declarative_base(metadata=metadata)
diff --git a/docs/tutorials/wiki2/src/installation/tutorial/models/mymodel.py b/docs/tutorials/wiki2/src/installation/tutorial/models/mymodel.py
new file mode 100644
index 000000000..d65a01a42
--- /dev/null
+++ b/docs/tutorials/wiki2/src/installation/tutorial/models/mymodel.py
@@ -0,0 +1,18 @@
+from sqlalchemy import (
+ Column,
+ Index,
+ Integer,
+ Text,
+)
+
+from .meta import Base
+
+
+class MyModel(Base):
+ __tablename__ = 'models'
+ id = Column(Integer, primary_key=True)
+ name = Column(Text)
+ value = Column(Integer)
+
+
+Index('my_index', MyModel.name, unique=True, mysql_length=255)
diff --git a/docs/tutorials/wiki2/src/installation/tutorial/routes.py b/docs/tutorials/wiki2/src/installation/tutorial/routes.py
new file mode 100644
index 000000000..25504ad4d
--- /dev/null
+++ b/docs/tutorials/wiki2/src/installation/tutorial/routes.py
@@ -0,0 +1,3 @@
+def includeme(config):
+ config.add_static_view('static', 'static', cache_max_age=3600)
+ config.add_route('home', '/')
diff --git a/docs/tutorials/wiki2/src/installation/tutorial/scripts/__init__.py b/docs/tutorials/wiki2/src/installation/tutorial/scripts/__init__.py
new file mode 100644
index 000000000..5bb534f79
--- /dev/null
+++ b/docs/tutorials/wiki2/src/installation/tutorial/scripts/__init__.py
@@ -0,0 +1 @@
+# package
diff --git a/docs/tutorials/wiki2/src/installation/tutorial/scripts/initializedb.py b/docs/tutorials/wiki2/src/installation/tutorial/scripts/initializedb.py
new file mode 100644
index 000000000..7307ecc5c
--- /dev/null
+++ b/docs/tutorials/wiki2/src/installation/tutorial/scripts/initializedb.py
@@ -0,0 +1,45 @@
+import os
+import sys
+import transaction
+
+from pyramid.paster import (
+ get_appsettings,
+ setup_logging,
+ )
+
+from pyramid.scripts.common import parse_vars
+
+from ..models.meta import Base
+from ..models import (
+ get_engine,
+ get_session_factory,
+ get_tm_session,
+ )
+from ..models import MyModel
+
+
+def usage(argv):
+ cmd = os.path.basename(argv[0])
+ print('usage: %s <config_uri> [var=value]\n'
+ '(example: "%s development.ini")' % (cmd, cmd))
+ sys.exit(1)
+
+
+def main(argv=sys.argv):
+ if len(argv) < 2:
+ usage(argv)
+ config_uri = argv[1]
+ options = parse_vars(argv[2:])
+ setup_logging(config_uri)
+ settings = get_appsettings(config_uri, options=options)
+
+ engine = get_engine(settings)
+ Base.metadata.create_all(engine)
+
+ session_factory = get_session_factory(engine)
+
+ with transaction.manager:
+ dbsession = get_tm_session(session_factory, transaction.manager)
+
+ model = MyModel(name='one', value=1)
+ dbsession.add(model)
diff --git a/docs/tutorials/wiki2/src/installation/tutorial/static/pyramid-16x16.png b/docs/tutorials/wiki2/src/installation/tutorial/static/pyramid-16x16.png
new file mode 100644
index 000000000..979203112
--- /dev/null
+++ b/docs/tutorials/wiki2/src/installation/tutorial/static/pyramid-16x16.png
Binary files differ
diff --git a/docs/tutorials/wiki2/src/installation/tutorial/static/pyramid.png b/docs/tutorials/wiki2/src/installation/tutorial/static/pyramid.png
new file mode 100644
index 000000000..4ab837be9
--- /dev/null
+++ b/docs/tutorials/wiki2/src/installation/tutorial/static/pyramid.png
Binary files differ
diff --git a/docs/tutorials/wiki2/src/installation/tutorial/static/theme.css b/docs/tutorials/wiki2/src/installation/tutorial/static/theme.css
new file mode 100644
index 000000000..0f4b1a4d4
--- /dev/null
+++ b/docs/tutorials/wiki2/src/installation/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/wiki2/src/installation/tutorial/static/theme.min.css b/docs/tutorials/wiki2/src/installation/tutorial/static/theme.min.css
new file mode 100644
index 000000000..0d25de5b6
--- /dev/null
+++ b/docs/tutorials/wiki2/src/installation/tutorial/static/theme.min.css
@@ -0,0 +1 @@
+@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:#fff;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:#fff}.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:#fff;text-decoration:underline}.starter-template .links ul li .icon-muted{color:#eb8b95;margin-right:5px}.starter-template .links ul li:hover .icon-muted{color:#fff}.starter-template .copyright{margin-top:10px;font-size:.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/wiki2/src/installation/tutorial/templates/404.jinja2 b/docs/tutorials/wiki2/src/installation/tutorial/templates/404.jinja2
new file mode 100644
index 000000000..1917f83c7
--- /dev/null
+++ b/docs/tutorials/wiki2/src/installation/tutorial/templates/404.jinja2
@@ -0,0 +1,8 @@
+{% extends "layout.jinja2" %}
+
+{% block content %}
+<div class="content">
+ <h1><span class="font-semi-bold">Pyramid</span> <span class="smaller">Alchemy scaffold</span></h1>
+ <p class="lead"><span class="font-semi-bold">404</span> Page Not Found</p>
+</div>
+{% endblock content %}
diff --git a/docs/tutorials/wiki2/src/installation/tutorial/templates/layout.jinja2 b/docs/tutorials/wiki2/src/installation/tutorial/templates/layout.jinja2
new file mode 100644
index 000000000..ab8c5ea3d
--- /dev/null
+++ b/docs/tutorials/wiki2/src/installation/tutorial/templates/layout.jinja2
@@ -0,0 +1,66 @@
+<!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>Alchemy 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">
+ {% block content %}
+ <p>No content</p>
+ {% endblock content %}
+ </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/wiki2/src/installation/tutorial/templates/mytemplate.jinja2 b/docs/tutorials/wiki2/src/installation/tutorial/templates/mytemplate.jinja2
new file mode 100644
index 000000000..6b49869c4
--- /dev/null
+++ b/docs/tutorials/wiki2/src/installation/tutorial/templates/mytemplate.jinja2
@@ -0,0 +1,8 @@
+{% extends "layout.jinja2" %}
+
+{% block content %}
+<div class="content">
+ <h1><span class="font-semi-bold">Pyramid</span> <span class="smaller">Alchemy 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>
+{% endblock content %}
diff --git a/docs/tutorials/wiki2/src/installation/tutorial/tests.py b/docs/tutorials/wiki2/src/installation/tutorial/tests.py
new file mode 100644
index 000000000..99e95efd3
--- /dev/null
+++ b/docs/tutorials/wiki2/src/installation/tutorial/tests.py
@@ -0,0 +1,65 @@
+import unittest
+import transaction
+
+from pyramid import testing
+
+
+def dummy_request(dbsession):
+ return testing.DummyRequest(dbsession=dbsession)
+
+
+class BaseTest(unittest.TestCase):
+ def setUp(self):
+ self.config = testing.setUp(settings={
+ 'sqlalchemy.url': 'sqlite:///:memory:'
+ })
+ self.config.include('.models')
+ settings = self.config.get_settings()
+
+ from .models import (
+ get_engine,
+ get_session_factory,
+ get_tm_session,
+ )
+
+ self.engine = get_engine(settings)
+ session_factory = get_session_factory(self.engine)
+
+ self.session = get_tm_session(session_factory, transaction.manager)
+
+ def init_database(self):
+ from .models.meta import Base
+ Base.metadata.create_all(self.engine)
+
+ def tearDown(self):
+ from .models.meta import Base
+
+ testing.tearDown()
+ transaction.abort()
+ Base.metadata.drop_all(self.engine)
+
+
+class TestMyViewSuccessCondition(BaseTest):
+
+ def setUp(self):
+ super(TestMyViewSuccessCondition, self).setUp()
+ self.init_database()
+
+ from .models import MyModel
+
+ model = MyModel(name='one', value=55)
+ self.session.add(model)
+
+ def test_passing_view(self):
+ from .views.default import my_view
+ info = my_view(dummy_request(self.session))
+ self.assertEqual(info['one'].name, 'one')
+ self.assertEqual(info['project'], 'tutorial')
+
+
+class TestMyViewFailureCondition(BaseTest):
+
+ def test_failing_view(self):
+ from .views.default import my_view
+ info = my_view(dummy_request(self.session))
+ self.assertEqual(info.status_int, 500)
diff --git a/docs/tutorials/wiki2/src/installation/tutorial/views/__init__.py b/docs/tutorials/wiki2/src/installation/tutorial/views/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/docs/tutorials/wiki2/src/installation/tutorial/views/__init__.py
diff --git a/docs/tutorials/wiki2/src/installation/tutorial/views/default.py b/docs/tutorials/wiki2/src/installation/tutorial/views/default.py
new file mode 100644
index 000000000..ad0c728d7
--- /dev/null
+++ b/docs/tutorials/wiki2/src/installation/tutorial/views/default.py
@@ -0,0 +1,33 @@
+from pyramid.response import Response
+from pyramid.view import view_config
+
+from sqlalchemy.exc import DBAPIError
+
+from ..models import MyModel
+
+
+@view_config(route_name='home', renderer='../templates/mytemplate.jinja2')
+def my_view(request):
+ try:
+ query = request.dbsession.query(MyModel)
+ one = query.filter(MyModel.name == 'one').first()
+ except DBAPIError:
+ return Response(db_err_msg, content_type='text/plain', status=500)
+ return {'one': one, 'project': 'tutorial'}
+
+
+db_err_msg = """\
+Pyramid is having a problem using your SQL database. The problem
+might be caused by one of the following things:
+
+1. You may need to run the "initialize_tutorial_db" script
+ to initialize your database tables. Check your virtual
+ environment's "bin" directory for this script and try to run it.
+
+2. Your database server may not be running. Check that the
+ database server referred to by the "sqlalchemy.url" setting in
+ your "development.ini" file is running.
+
+After you fix the problem, please restart the Pyramid application to
+try it again.
+"""
diff --git a/docs/tutorials/wiki2/src/installation/tutorial/views/notfound.py b/docs/tutorials/wiki2/src/installation/tutorial/views/notfound.py
new file mode 100644
index 000000000..69d6e2804
--- /dev/null
+++ b/docs/tutorials/wiki2/src/installation/tutorial/views/notfound.py
@@ -0,0 +1,7 @@
+from pyramid.view import notfound_view_config
+
+
+@notfound_view_config(renderer='../templates/404.jinja2')
+def notfound_view(request):
+ request.response.status = 404
+ return {}