Steve Piercy
2016-12-25 b488f7f72ff36526cf21798c91c7f09eaf1afa7a
quick_tour - "Databases" updates for cookiecutter
- add src files
- adjust line numbers
1 files deleted
16 files modified
342 ■■■■■ changed files
docs/quick_tour.rst 41 ●●●● patch | view | raw | blame | history
docs/quick_tour/sqla_demo/CHANGES.txt 2 ●●● patch | view | raw | blame | history
docs/quick_tour/sqla_demo/MANIFEST.in 2 ●●● patch | view | raw | blame | history
docs/quick_tour/sqla_demo/README.txt 31 ●●●● patch | view | raw | blame | history
docs/quick_tour/sqla_demo/development.ini 1 ●●●● patch | view | raw | blame | history
docs/quick_tour/sqla_demo/production.ini 6 ●●●●● patch | view | raw | blame | history
docs/quick_tour/sqla_demo/setup.cfg 27 ●●●●● patch | view | raw | blame | history
docs/quick_tour/sqla_demo/setup.py 63 ●●●●● patch | view | raw | blame | history
docs/quick_tour/sqla_demo/sqla_demo/__init__.py 5 ●●●●● patch | view | raw | blame | history
docs/quick_tour/sqla_demo/sqla_demo/models/__init__.py 74 ●●●●● patch | view | raw | blame | history
docs/quick_tour/sqla_demo/sqla_demo/models/meta.py 33 ●●●●● patch | view | raw | blame | history
docs/quick_tour/sqla_demo/sqla_demo/models/mymodel.py 5 ●●●●● patch | view | raw | blame | history
docs/quick_tour/sqla_demo/sqla_demo/scripts/initializedb.py 18 ●●●● patch | view | raw | blame | history
docs/quick_tour/sqla_demo/sqla_demo/templates/layout.jinja2 8 ●●●●● patch | view | raw | blame | history
docs/quick_tour/sqla_demo/sqla_demo/templates/mytemplate.jinja2 4 ●●●● patch | view | raw | blame | history
docs/quick_tour/sqla_demo/sqla_demo/tests.py 16 ●●●● patch | view | raw | blame | history
docs/quick_tour/sqla_demo/sqla_demo/views/default.py 6 ●●●●● patch | view | raw | blame | history
docs/quick_tour.rst
@@ -519,7 +519,7 @@
#. ``project_name [Pyramid Scaffold]: hello_world``
#. ``repo_name [scaffold]: hello_world``
We then run through the following commands
We then run through the following commands.
.. code-block:: bash
@@ -532,7 +532,7 @@
    # ...and into which we install our project and its testing requirements.
    $ env/bin/pip install -e ".[testing]"
    # Reset our environment variable for a new virtual environment.
    $ export VENV=~/env/hello_world/env
    $ export VENV=~/hello_world/env
We are moving in the direction of a full-featured Pyramid project, with a
proper setup for Python standards (packaging) and Pyramid configuration. This
@@ -854,13 +854,34 @@
usually leads to the mega-quality *SQLAlchemy*, a Python package that greatly
eases working with databases.
Pyramid and SQLAlchemy are great friends. That friendship includes a scaffold!
Pyramid and SQLAlchemy are great friends. That friendship includes a cookiecutter!
.. code-block:: bash
  $ $VENV/bin/pcreate --scaffold alchemy sqla_demo
  $ cd sqla_demo
  $ $VENV/bin/pip install -e .
    $ cd ~
    $ env/bin/cookiecutter https://github.com/Pylons/pyramid-cookiecutter-alchemy
If prompted for the first item, accept the default ``yes`` by hitting return.
#. ``You've cloned ~/.cookiecutters/pyramid-cookiecutter-alchemy before. Is it
   okay to delete and re-clone it? [yes]:``
#. ``project_name [Pyramid Scaffold]: sqla_demo``
#. ``repo_name [scaffold]: sqla_demo``
We then run through the following commands as before.
.. code-block:: bash
    # Change directory into your newly created project.
    $ cd sqla_demo
    # Create a new virtual environment...
    $ python3 -m venv env
    # ...where we upgrade packaging tools...
    $ env/bin/pip install --upgrade pip setuptools
    # ...and into which we install our project and its testing requirements.
    $ env/bin/pip install -e ".[testing]"
    # Reset our environment variable for a new virtual environment.
    $ export VENV=~/sqla_demo/env
We now have a working sample SQLAlchemy application with all dependencies
installed. The sample project provides a console script to initialize a SQLite
@@ -877,16 +898,16 @@
.. literalinclude:: quick_tour/sqla_demo/sqla_demo/models/mymodel.py
    :language: python
    :start-after: Start Sphinx Include
    :end-before: End Sphinx Include
    :lineno-match:
    :pyobject: MyModel
View code, which mediates the logic between web requests and the rest of the
system, can then easily get at the data thanks to SQLAlchemy:
.. literalinclude:: quick_tour/sqla_demo/sqla_demo/views/default.py
    :language: python
    :start-after: Start Sphinx Include
    :end-before: End Sphinx Include
    :lineno-match:
    :lines: 13
.. seealso:: See also:
    :ref:`Quick Tutorial Databases <qtut_databases>`, `SQLAlchemy
docs/quick_tour/sqla_demo/CHANGES.txt
@@ -1,4 +1,4 @@
0.0
---
-  Initial version
- Initial version.
docs/quick_tour/sqla_demo/MANIFEST.in
@@ -1,2 +1,2 @@
include *.txt *.ini *.cfg *.rst
recursive-include sqla_demo *.ico *.png *.css *.gif *.jpg *.pt *.txt *.mak *.mako *.js *.html *.xml
recursive-include sqla_demo *.ico *.png *.css *.gif *.jpg *.pt *.txt *.mak *.mako *.js *.html *.xml *.jinja2
docs/quick_tour/sqla_demo/README.txt
@@ -1,14 +1,33 @@
sqla_demo README
==================
sqla_demo
===============================
Getting Started
---------------
- cd <directory containing this file>
- Change directory into your newly created project.
- $VENV/bin/pip install -e .
    cd sqla_demo
- $VENV/bin/initialize_sqla_demo_db development.ini
- Create a Python virtual environment.
- $VENV/bin/pserve development.ini
    python3 -m venv env
- Upgrade packaging tools.
    env/bin/pip install --upgrade pip setuptools
- Install the project in editable mode with its testing requirements.
    env/bin/pip install -e ".[testing]"
- Configure the database.
    env/bin/initialize_sqla_demo_db development.ini
- Run your project's tests.
    env/bin/pytest
- Run your project.
    env/bin/pserve development.ini
docs/quick_tour/sqla_demo/development.ini
@@ -13,7 +13,6 @@
pyramid.default_locale_name = en
pyramid.includes =
    pyramid_debugtoolbar
    pyramid_tm
sqlalchemy.url = sqlite:///%(here)s/sqla_demo.sqlite
docs/quick_tour/sqla_demo/production.ini
@@ -11,11 +11,13 @@
pyramid.debug_notfound = false
pyramid.debug_routematch = false
pyramid.default_locale_name = en
pyramid.includes =
    pyramid_tm
sqlalchemy.url = sqlite:///%(here)s/sqla_demo.sqlite
###
# wsgi server configuration
###
[server:main]
use = egg:waitress#main
listen = *:6543
docs/quick_tour/sqla_demo/setup.cfg
File was deleted
docs/quick_tour/sqla_demo/setup.py
@@ -17,31 +17,42 @@
    'transaction',
    'zope.sqlalchemy',
    'waitress',
    ]
]
setup(name='sqla_demo',
      version='0.0',
      description='sqla_demo',
      long_description=README + '\n\n' + CHANGES,
      classifiers=[
        "Programming Language :: Python",
        "Framework :: Pyramid",
        "Topic :: Internet :: WWW/HTTP",
        "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
tests_require = [
    'WebTest >= 1.3.1',  # py3 compat
    'pytest',
    'pytest-cov',
]
setup(
    name='sqla_demo',
    version='0.0',
    description='sqla_demo',
    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 pyramid pylons',
    packages=find_packages(),
    include_package_data=True,
    zip_safe=False,
    extras_require={
        'testing': tests_require,
    },
    install_requires=requires,
    entry_points={
        'paste.app_factory': [
            'main = sqla_demo:main',
        ],
      author='',
      author_email='',
      url='',
      keywords='web wsgi bfg pylons pyramid',
      packages=find_packages(),
      include_package_data=True,
      zip_safe=False,
      test_suite='sqla_demo',
      install_requires=requires,
      entry_points="""\
      [paste.app_factory]
      main = sqla_demo:main
      [console_scripts]
      initialize_sqla_demo_db = sqla_demo.scripts.initializedb:main
      """,
      )
        'console_scripts': [
            'initialize_sqla_demo_db = sqla_demo.scripts.initializedb:main',
        ],
    },
)
docs/quick_tour/sqla_demo/sqla_demo/__init__.py
@@ -6,8 +6,7 @@
    """
    config = Configurator(settings=settings)
    config.include('pyramid_jinja2')
    config.include('.models.meta')
    config.add_static_view('static', 'static', cache_max_age=3600)
    config.add_route('home', '/')
    config.include('.models')
    config.include('.routes')
    config.scan()
    return config.make_wsgi_app()
docs/quick_tour/sqla_demo/sqla_demo/models/__init__.py
@@ -1,7 +1,73 @@
from sqlalchemy import engine_from_config
from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm import configure_mappers
# import all models classes here for sqlalchemy mappers
# to pick up
from .mymodel import MyModel  # noqa
import zope.sqlalchemy
# run configure mappers to ensure we avoid any race conditions
# 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('sqla_demo.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
    )
docs/quick_tour/sqla_demo/sqla_demo/models/meta.py
@@ -1,8 +1,5 @@
from sqlalchemy import engine_from_config
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy.schema import MetaData
import zope.sqlalchemy
# Recommended naming convention used by Alembic, as various different database
# providers will autogenerate vastly different names making migrations more
@@ -17,33 +14,3 @@
metadata = MetaData(naming_convention=NAMING_CONVENTION)
Base = declarative_base(metadata=metadata)
def includeme(config):
    settings = config.get_settings()
    dbmaker = get_dbmaker(get_engine(settings))
    config.add_request_method(
        lambda r: get_session(r.tm, dbmaker),
        'dbsession',
        reify=True
    )
    config.include('pyramid_tm')
def get_session(transaction_manager, dbmaker):
    dbsession = dbmaker()
    zope.sqlalchemy.register(dbsession,
                             transaction_manager=transaction_manager)
    return dbsession
def get_engine(settings, prefix='sqlalchemy.'):
    return engine_from_config(settings, prefix)
def get_dbmaker(engine):
    dbmaker = sessionmaker()
    dbmaker.configure(bind=engine)
    return dbmaker
docs/quick_tour/sqla_demo/sqla_demo/models/mymodel.py
@@ -1,4 +1,3 @@
from .meta import Base
from sqlalchemy import (
    Column,
    Index,
@@ -6,14 +5,14 @@
    Text,
)
from .meta import Base
# Start Sphinx Include
class MyModel(Base):
    __tablename__ = 'models'
    id = Column(Integer, primary_key=True)
    name = Column(Text)
    value = Column(Integer)
    # End Sphinx Include
Index('my_index', MyModel.name, unique=True, mysql_length=255)
docs/quick_tour/sqla_demo/sqla_demo/scripts/initializedb.py
@@ -9,13 +9,13 @@
from pyramid.scripts.common import parse_vars
from ..models.meta import (
    Base,
    get_session,
from ..models.meta import Base
from ..models import (
    get_engine,
    get_dbmaker,
    get_session_factory,
    get_tm_session,
    )
from ..models.mymodel import MyModel
from ..models import MyModel
def usage(argv):
@@ -34,12 +34,12 @@
    settings = get_appsettings(config_uri, options=options)
    engine = get_engine(settings)
    dbmaker = get_dbmaker(engine)
    dbsession = get_session(transaction.manager, dbmaker)
    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)
docs/quick_tour/sqla_demo/sqla_demo/templates/layout.jinja2
@@ -8,7 +8,7 @@
    <meta name="author" content="Pylons Project">
    <link rel="shortcut icon" href="{{request.static_url('sqla_demo:static/pyramid-16x16.png')}}">
    <title>Alchemy Scaffold for The Pyramid Web Framework</title>
    <title>Cookiecutter Alchemy project 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">
@@ -29,7 +29,7 @@
      <div class="container">
        <div class="row">
          <div class="col-md-2">
            <img class="logo img-responsive" src="{{request.static_url('sqla_demo:static/pyramid.png')}}" alt="pyramid web framework">
            <img class="logo img-responsive" src="{{request.static_url('sqla_demo:static/pyramid.png') }}" alt="pyramid web framework">
          </div>
          <div class="col-md-10">
            {% block content %}
@@ -40,10 +40,8 @@
        <div class="row">
          <div class="links">
            <ul>
              <li class="current-version">Generated by v1.7.dev0</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-globe icon-muted"></i><a href="https://webchat.freenode.net/?channels=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>
docs/quick_tour/sqla_demo/sqla_demo/templates/mytemplate.jinja2
@@ -2,7 +2,7 @@
{% 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.dev0</span>.</p>
  <h1><span class="font-semi-bold">Pyramid</span> <span class="smaller">Alchemy project</span></h1>
  <p class="lead">Welcome to <span class="font-normal">sqla_demo</span>, a&nbsp;Pyramid application generated&nbsp;by<br><span class="font-normal">Cookiecutter</span>.</p>
</div>
{% endblock content %}
docs/quick_tour/sqla_demo/sqla_demo/tests.py
@@ -13,19 +13,19 @@
        self.config = testing.setUp(settings={
            'sqlalchemy.url': 'sqlite:///:memory:'
        })
        self.config.include('.models.meta')
        self.config.include('.models')
        settings = self.config.get_settings()
        from .models.meta import (
            get_session,
        from .models import (
            get_engine,
            get_dbmaker,
            get_session_factory,
            get_tm_session,
            )
        self.engine = get_engine(settings)
        dbmaker = get_dbmaker(self.engine)
        session_factory = get_session_factory(self.engine)
        self.session = get_session(transaction.manager, dbmaker)
        self.session = get_tm_session(session_factory, transaction.manager)
    def init_database(self):
        from .models.meta import Base
@@ -36,7 +36,7 @@
        testing.tearDown()
        transaction.abort()
        Base.metadata.create_all(self.engine)
        Base.metadata.drop_all(self.engine)
class TestMyViewSuccessCondition(BaseTest):
@@ -45,7 +45,7 @@
        super(TestMyViewSuccessCondition, self).setUp()
        self.init_database()
        from .models.mymodel import MyModel
        from .models import MyModel
        model = MyModel(name='one', value=55)
        self.session.add(model)
docs/quick_tour/sqla_demo/sqla_demo/views/default.py
@@ -3,18 +3,16 @@
from sqlalchemy.exc import DBAPIError
from ..models.mymodel import MyModel
from ..models import MyModel
@view_config(route_name='home', renderer='../templates/mytemplate.jinja2')
def my_view(request):
    try:
        query = request.dbsession.query(MyModel)
        # Start Sphinx Include
        one = query.filter(MyModel.name == 'one').first()
        # End Sphinx Include
    except DBAPIError:
        return Response(db_err_msg, content_type='text/plain', status_int=500)
        return Response(db_err_msg, content_type='text/plain', status=500)
    return {'one': one, 'project': 'sqla_demo'}