diff --git a/pyramid_cookie_sql/.coveragerc b/pyramid_cookie_sql/.coveragerc
new file mode 100644
index 0000000..d8aee03
--- /dev/null
+++ b/pyramid_cookie_sql/.coveragerc
@@ -0,0 +1,3 @@
+[run]
+source = cookies
+omit = cookies/test*
diff --git a/pyramid_cookie_sql/.gitignore b/pyramid_cookie_sql/.gitignore
new file mode 100644
index 0000000..1853d98
--- /dev/null
+++ b/pyramid_cookie_sql/.gitignore
@@ -0,0 +1,21 @@
+*.egg
+*.egg-info
+*.pyc
+*$py.class
+*~
+.coverage
+coverage.xml
+build/
+dist/
+.tox/
+nosetests.xml
+env*/
+tmp/
+Data.fs*
+*.sublime-project
+*.sublime-workspace
+.*.sw?
+.sw?
+.DS_Store
+coverage
+test
diff --git a/pyramid_cookie_sql/CHANGES.txt b/pyramid_cookie_sql/CHANGES.txt
new file mode 100644
index 0000000..14b902f
--- /dev/null
+++ b/pyramid_cookie_sql/CHANGES.txt
@@ -0,0 +1,4 @@
+0.0
+---
+
+- Initial version.
diff --git a/pyramid_cookie_sql/MANIFEST.in b/pyramid_cookie_sql/MANIFEST.in
new file mode 100644
index 0000000..b64c3d0
--- /dev/null
+++ b/pyramid_cookie_sql/MANIFEST.in
@@ -0,0 +1,2 @@
+include *.txt *.ini *.cfg *.rst
+recursive-include cookies *.ico *.png *.css *.gif *.jpg *.pt *.txt *.mak *.mako *.js *.html *.xml *.jinja2
diff --git a/pyramid_cookie_sql/README.txt b/pyramid_cookie_sql/README.txt
new file mode 100644
index 0000000..062815c
--- /dev/null
+++ b/pyramid_cookie_sql/README.txt
@@ -0,0 +1,43 @@
+cookies
+=======
+
+Getting Started
+---------------
+
+- Change directory into your newly created project.
+
+ cd cookies
+
+- Create a Python virtual environment.
+
+ 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]"
+
+- Initialize and upgrade the database using Alembic.
+
+ - Generate your first revision.
+
+ env/bin/alembic -c development.ini revision --autogenerate -m "init"
+
+ - Upgrade to that revision.
+
+ env/bin/alembic -c development.ini upgrade head
+
+- Load default data into the database using a script.
+
+ env/bin/initialize_cookies_db development.ini
+
+- Run your project's tests.
+
+ env/bin/pytest
+
+- Run your project.
+
+ env/bin/pserve development.ini
diff --git a/pyramid_cookie_sql/cookies/__init__.py b/pyramid_cookie_sql/cookies/__init__.py
new file mode 100644
index 0000000..5c2ba5c
--- /dev/null
+++ b/pyramid_cookie_sql/cookies/__init__.py
@@ -0,0 +1,12 @@
+from pyramid.config import Configurator
+
+
+def main(global_config, **settings):
+ """ This function returns a Pyramid WSGI application.
+ """
+ with Configurator(settings=settings) as config:
+ config.include('.models')
+ config.include('pyramid_jinja2')
+ config.include('.routes')
+ config.scan()
+ return config.make_wsgi_app()
diff --git a/pyramid_cookie_sql/cookies/alembic/env.py b/pyramid_cookie_sql/cookies/alembic/env.py
new file mode 100644
index 0000000..48b7221
--- /dev/null
+++ b/pyramid_cookie_sql/cookies/alembic/env.py
@@ -0,0 +1,58 @@
+"""Pyramid bootstrap environment. """
+from alembic import context
+from pyramid.paster import get_appsettings, setup_logging
+from sqlalchemy import engine_from_config
+
+from cookies.models.meta import Base
+
+config = context.config
+
+setup_logging(config.config_file_name)
+
+settings = get_appsettings(config.config_file_name)
+target_metadata = Base.metadata
+
+
+def run_migrations_offline():
+ """Run migrations in 'offline' mode.
+
+ This configures the context with just a URL
+ and not an Engine, though an Engine is acceptable
+ here as well. By skipping the Engine creation
+ we don't even need a DBAPI to be available.
+
+ Calls to context.execute() here emit the given string to the
+ script output.
+
+ """
+ context.configure(url=settings['sqlalchemy.url'])
+ with context.begin_transaction():
+ context.run_migrations()
+
+
+def run_migrations_online():
+ """Run migrations in 'online' mode.
+
+ In this scenario we need to create an Engine
+ and associate a connection with the context.
+
+ """
+ engine = engine_from_config(settings, prefix='sqlalchemy.')
+
+ connection = engine.connect()
+ context.configure(
+ connection=connection,
+ target_metadata=target_metadata
+ )
+
+ try:
+ with context.begin_transaction():
+ context.run_migrations()
+ finally:
+ connection.close()
+
+
+if context.is_offline_mode():
+ run_migrations_offline()
+else:
+ run_migrations_online()
diff --git a/pyramid_cookie_sql/cookies/alembic/script.py.mako b/pyramid_cookie_sql/cookies/alembic/script.py.mako
new file mode 100644
index 0000000..535780d
--- /dev/null
+++ b/pyramid_cookie_sql/cookies/alembic/script.py.mako
@@ -0,0 +1,22 @@
+"""${message}
+
+Revision ID: ${up_revision}
+Revises: ${down_revision | comma,n}
+Create Date: ${create_date}
+
+"""
+from alembic import op
+import sqlalchemy as sa
+${imports if imports else ""}
+
+# revision identifiers, used by Alembic.
+revision = ${repr(up_revision)}
+down_revision = ${repr(down_revision)}
+branch_labels = ${repr(branch_labels)}
+depends_on = ${repr(depends_on)}
+
+def upgrade():
+ ${upgrades if upgrades else "pass"}
+
+def downgrade():
+ ${downgrades if downgrades else "pass"}
diff --git a/pyramid_cookie_sql/cookies/alembic/versions/README.txt b/pyramid_cookie_sql/cookies/alembic/versions/README.txt
new file mode 100644
index 0000000..b0d704d
--- /dev/null
+++ b/pyramid_cookie_sql/cookies/alembic/versions/README.txt
@@ -0,0 +1 @@
+Placeholder for alembic versions
diff --git a/pyramid_cookie_sql/cookies/models/__init__.py b/pyramid_cookie_sql/cookies/models/__init__.py
new file mode 100644
index 0000000..863a42d
--- /dev/null
+++ b/pyramid_cookie_sql/cookies/models/__init__.py
@@ -0,0 +1,77 @@
+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('cookies.models')``.
+
+ """
+ settings = config.get_settings()
+ settings['tm.manager_hook'] = 'pyramid_tm.explicit_manager'
+
+ # use pyramid_tm to hook the transaction lifecycle to the request
+ config.include('pyramid_tm')
+
+ # use pyramid_retry to retry a request when transient exceptions occur
+ config.include('pyramid_retry')
+
+ 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/pyramid_cookie_sql/cookies/models/meta.py b/pyramid_cookie_sql/cookies/models/meta.py
new file mode 100644
index 0000000..02285b3
--- /dev/null
+++ b/pyramid_cookie_sql/cookies/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.zzzcomputing.com/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/pyramid_cookie_sql/cookies/models/mymodel.py b/pyramid_cookie_sql/cookies/models/mymodel.py
new file mode 100644
index 0000000..d65a01a
--- /dev/null
+++ b/pyramid_cookie_sql/cookies/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/pyramid_cookie_sql/cookies/pshell.py b/pyramid_cookie_sql/cookies/pshell.py
new file mode 100644
index 0000000..b0847ee
--- /dev/null
+++ b/pyramid_cookie_sql/cookies/pshell.py
@@ -0,0 +1,13 @@
+from . import models
+
+
+def setup(env):
+ request = env['request']
+
+ # start a transaction
+ request.tm.begin()
+
+ # inject some vars into the shell builtins
+ env['tm'] = request.tm
+ env['dbsession'] = request.dbsession
+ env['models'] = models
diff --git a/pyramid_cookie_sql/cookies/routes.py b/pyramid_cookie_sql/cookies/routes.py
new file mode 100644
index 0000000..25504ad
--- /dev/null
+++ b/pyramid_cookie_sql/cookies/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/pyramid_cookie_sql/cookies/scripts/__init__.py b/pyramid_cookie_sql/cookies/scripts/__init__.py
new file mode 100644
index 0000000..5bb534f
--- /dev/null
+++ b/pyramid_cookie_sql/cookies/scripts/__init__.py
@@ -0,0 +1 @@
+# package
diff --git a/pyramid_cookie_sql/cookies/scripts/initialize_db.py b/pyramid_cookie_sql/cookies/scripts/initialize_db.py
new file mode 100644
index 0000000..c629d17
--- /dev/null
+++ b/pyramid_cookie_sql/cookies/scripts/initialize_db.py
@@ -0,0 +1,48 @@
+import argparse
+import sys
+
+from pyramid.paster import bootstrap, setup_logging
+from sqlalchemy.exc import OperationalError
+
+from .. import models
+
+
+def setup_models(dbsession):
+ """
+ Add or update models / fixtures in the database.
+
+ """
+ model = models.mymodel.MyModel(name='one', value=1)
+ dbsession.add(model)
+
+
+def parse_args(argv):
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ 'config_uri',
+ help='Configuration file, e.g., development.ini',
+ )
+ return parser.parse_args(argv[1:])
+
+
+def main(argv=sys.argv):
+ args = parse_args(argv)
+ setup_logging(args.config_uri)
+ env = bootstrap(args.config_uri)
+
+ try:
+ with env['request'].tm:
+ dbsession = env['request'].dbsession
+ setup_models(dbsession)
+ except OperationalError:
+ print('''
+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 initialize your database tables with `alembic`.
+ Check your README.txt for description 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.
+ ''')
diff --git a/pyramid_cookie_sql/cookies/static/pyramid-16x16.png b/pyramid_cookie_sql/cookies/static/pyramid-16x16.png
new file mode 100644
index 0000000..9792031
Binary files /dev/null and b/pyramid_cookie_sql/cookies/static/pyramid-16x16.png differ
diff --git a/pyramid_cookie_sql/cookies/static/pyramid.png b/pyramid_cookie_sql/cookies/static/pyramid.png
new file mode 100644
index 0000000..4ab837b
Binary files /dev/null and b/pyramid_cookie_sql/cookies/static/pyramid.png differ
diff --git a/pyramid_cookie_sql/cookies/static/theme.css b/pyramid_cookie_sql/cookies/static/theme.css
new file mode 100644
index 0000000..0f4b1a4
--- /dev/null
+++ b/pyramid_cookie_sql/cookies/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/pyramid_cookie_sql/cookies/templates/404.jinja2 b/pyramid_cookie_sql/cookies/templates/404.jinja2
new file mode 100644
index 0000000..aaf1241
--- /dev/null
+++ b/pyramid_cookie_sql/cookies/templates/404.jinja2
@@ -0,0 +1,8 @@
+{% extends "layout.jinja2" %}
+
+{% block content %}
+
+
Pyramid Starter project
+
404 Page Not Found
+
+{% endblock content %}
diff --git a/pyramid_cookie_sql/cookies/templates/layout.jinja2 b/pyramid_cookie_sql/cookies/templates/layout.jinja2
new file mode 100644
index 0000000..23aad57
--- /dev/null
+++ b/pyramid_cookie_sql/cookies/templates/layout.jinja2
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+ Cookiecutter Starter project for the Pyramid Web Framework
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 }})
+
+
+ {% block content %}
+
No content
+ {% endblock content %}
+
+
+
+
+
+ Copyright © Pylons Project
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pyramid_cookie_sql/cookies/templates/mytemplate.jinja2 b/pyramid_cookie_sql/cookies/templates/mytemplate.jinja2
new file mode 100644
index 0000000..f2e7283
--- /dev/null
+++ b/pyramid_cookie_sql/cookies/templates/mytemplate.jinja2
@@ -0,0 +1,8 @@
+{% extends "layout.jinja2" %}
+
+{% block content %}
+
+
Pyramid Starter project
+
Welcome to {{project}}, a Pyramid application generated by
Cookiecutter.
+
+{% endblock content %}
diff --git a/pyramid_cookie_sql/cookies/tests.py b/pyramid_cookie_sql/cookies/tests.py
new file mode 100644
index 0000000..5acc108
--- /dev/null
+++ b/pyramid_cookie_sql/cookies/tests.py
@@ -0,0 +1,66 @@
+import unittest
+
+from pyramid import testing
+
+import transaction
+
+
+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'], 'cookies')
+
+
+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/pyramid_cookie_sql/cookies/views/__init__.py b/pyramid_cookie_sql/cookies/views/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/pyramid_cookie_sql/cookies/views/default.py b/pyramid_cookie_sql/cookies/views/default.py
new file mode 100644
index 0000000..a6c0ec6
--- /dev/null
+++ b/pyramid_cookie_sql/cookies/views/default.py
@@ -0,0 +1,32 @@
+from pyramid.view import view_config
+from pyramid.response import Response
+
+from sqlalchemy.exc import DBAPIError
+
+from .. import models
+
+
+@view_config(route_name='home', renderer='../templates/mytemplate.jinja2')
+def my_view(request):
+ try:
+ query = request.dbsession.query(models.MyModel)
+ one = query.filter(models.MyModel.name == 'one').first()
+ except DBAPIError:
+ return Response(db_err_msg, content_type='text/plain', status=500)
+ return {'one': one, 'project': 'cookies'}
+
+
+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 initialize your database tables with `alembic`.
+ Check your README.txt for descriptions 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/pyramid_cookie_sql/cookies/views/notfound.py b/pyramid_cookie_sql/cookies/views/notfound.py
new file mode 100644
index 0000000..69d6e28
--- /dev/null
+++ b/pyramid_cookie_sql/cookies/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 {}
diff --git a/pyramid_cookie_sql/development.ini b/pyramid_cookie_sql/development.ini
new file mode 100644
index 0000000..954a7a0
--- /dev/null
+++ b/pyramid_cookie_sql/development.ini
@@ -0,0 +1,80 @@
+###
+# app configuration
+# https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
+###
+
+[app:main]
+use = egg:cookies
+
+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
+
+sqlalchemy.url = sqlite:///%(here)s/cookies.sqlite
+
+retry.attempts = 3
+
+# By default, the toolbar only appears for clients from IP addresses
+# '127.0.0.1' and '::1'.
+# debugtoolbar.hosts = 127.0.0.1 ::1
+
+[pshell]
+setup = cookies.pshell.setup
+
+###
+# wsgi server configuration
+###
+
+[alembic]
+# path to migration scripts
+script_location = cookies/alembic
+file_template = %%(year)d%%(month).2d%%(day).2d_%%(rev)s
+# file_template = %%(rev)s_%%(slug)s
+
+[server:main]
+use = egg:waitress#main
+listen = localhost:6543
+
+###
+# logging configuration
+# https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
+###
+
+[loggers]
+keys = root, cookies, sqlalchemy
+
+[handlers]
+keys = console
+
+[formatters]
+keys = generic
+
+[logger_root]
+level = INFO
+handlers = console
+
+[logger_cookies]
+level = DEBUG
+handlers =
+qualname = cookies
+
+[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/pyramid_cookie_sql/production.ini b/pyramid_cookie_sql/production.ini
new file mode 100644
index 0000000..fc2eb61
--- /dev/null
+++ b/pyramid_cookie_sql/production.ini
@@ -0,0 +1,74 @@
+###
+# app configuration
+# https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
+###
+
+[app:main]
+use = egg:cookies
+
+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/cookies.sqlite
+
+retry.attempts = 3
+
+[pshell]
+setup = cookies.pshell.setup
+
+###
+# wsgi server configuration
+###
+
+[alembic]
+# path to migration scripts
+script_location = cookies/alembic
+file_template = %%(year)d%%(month).2d%%(day).2d_%%(rev)s
+# file_template = %%(rev)s_%%(slug)s
+
+[server:main]
+use = egg:waitress#main
+listen = *:6543
+
+###
+# logging configuration
+# https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
+###
+
+[loggers]
+keys = root, cookies, sqlalchemy
+
+[handlers]
+keys = console
+
+[formatters]
+keys = generic
+
+[logger_root]
+level = WARN
+handlers = console
+
+[logger_cookies]
+level = WARN
+handlers =
+qualname = cookies
+
+[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/pyramid_cookie_sql/pytest.ini b/pyramid_cookie_sql/pytest.ini
new file mode 100644
index 0000000..b48d1f9
--- /dev/null
+++ b/pyramid_cookie_sql/pytest.ini
@@ -0,0 +1,3 @@
+[pytest]
+testpaths = cookies
+python_files = test*.py
diff --git a/pyramid_cookie_sql/setup.py b/pyramid_cookie_sql/setup.py
new file mode 100644
index 0000000..bc82a9d
--- /dev/null
+++ b/pyramid_cookie_sql/setup.py
@@ -0,0 +1,61 @@
+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 = [
+ 'plaster_pastedeploy',
+ 'pyramid',
+ 'pyramid_jinja2',
+ 'pyramid_debugtoolbar',
+ 'waitress',
+ 'alembic',
+ 'pyramid_retry',
+ 'pyramid_tm',
+ 'SQLAlchemy',
+ 'transaction',
+ 'zope.sqlalchemy',
+]
+
+tests_require = [
+ 'WebTest >= 1.3.1', # py3 compat
+ 'pytest >= 3.7.4',
+ 'pytest-cov',
+]
+
+setup(
+ name='cookies',
+ version='0.0',
+ description='cookies',
+ 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 = cookies:main',
+ ],
+ 'console_scripts': [
+ 'initialize_cookies_db=cookies.scripts.initialize_db:main',
+ ],
+ },
+)
diff --git a/pyramid_cookie_trav/.coveragerc b/pyramid_cookie_trav/.coveragerc
new file mode 100644
index 0000000..0a56c42
--- /dev/null
+++ b/pyramid_cookie_trav/.coveragerc
@@ -0,0 +1,3 @@
+[run]
+source = cookie
+omit = cookie/test*
diff --git a/pyramid_cookie_trav/.gitignore b/pyramid_cookie_trav/.gitignore
new file mode 100644
index 0000000..1853d98
--- /dev/null
+++ b/pyramid_cookie_trav/.gitignore
@@ -0,0 +1,21 @@
+*.egg
+*.egg-info
+*.pyc
+*$py.class
+*~
+.coverage
+coverage.xml
+build/
+dist/
+.tox/
+nosetests.xml
+env*/
+tmp/
+Data.fs*
+*.sublime-project
+*.sublime-workspace
+.*.sw?
+.sw?
+.DS_Store
+coverage
+test
diff --git a/pyramid_cookie_trav/CHANGES.txt b/pyramid_cookie_trav/CHANGES.txt
new file mode 100644
index 0000000..14b902f
--- /dev/null
+++ b/pyramid_cookie_trav/CHANGES.txt
@@ -0,0 +1,4 @@
+0.0
+---
+
+- Initial version.
diff --git a/pyramid_cookie_trav/MANIFEST.in b/pyramid_cookie_trav/MANIFEST.in
new file mode 100644
index 0000000..6f8c57c
--- /dev/null
+++ b/pyramid_cookie_trav/MANIFEST.in
@@ -0,0 +1,2 @@
+include *.txt *.ini *.cfg *.rst
+recursive-include cookie *.ico *.png *.css *.gif *.jpg *.pt *.txt *.mak *.mako *.js *.html *.xml *.jinja2
diff --git a/pyramid_cookie_trav/README.txt b/pyramid_cookie_trav/README.txt
new file mode 100644
index 0000000..8d3fc34
--- /dev/null
+++ b/pyramid_cookie_trav/README.txt
@@ -0,0 +1,29 @@
+cookie
+======
+
+Getting Started
+---------------
+
+- Change directory into your newly created project.
+
+ cd cookie
+
+- Create a Python virtual environment.
+
+ 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]"
+
+- Run your project's tests.
+
+ env/bin/pytest
+
+- Run your project.
+
+ env/bin/pserve development.ini
diff --git a/pyramid_cookie_trav/cookie/__init__.py b/pyramid_cookie_trav/cookie/__init__.py
new file mode 100644
index 0000000..badb31b
--- /dev/null
+++ b/pyramid_cookie_trav/cookie/__init__.py
@@ -0,0 +1,23 @@
+from pyramid.config import Configurator
+from pyramid_zodbconn import get_connection
+from .models import appmaker
+
+
+def root_factory(request):
+ conn = get_connection(request)
+ return appmaker(conn.root())
+
+
+def main(global_config, **settings):
+ """ This function returns a Pyramid WSGI application.
+ """
+ with Configurator(settings=settings) as config:
+ settings['tm.manager_hook'] = 'pyramid_tm.explicit_manager'
+ config.include('pyramid_tm')
+ config.include('pyramid_retry')
+ config.include('pyramid_zodbconn')
+ config.set_root_factory(root_factory)
+ config.include('pyramid_jinja2')
+ config.include('.routes')
+ config.scan()
+ return config.make_wsgi_app()
diff --git a/pyramid_cookie_trav/cookie/models/__init__.py b/pyramid_cookie_trav/cookie/models/__init__.py
new file mode 100644
index 0000000..aca6a41
--- /dev/null
+++ b/pyramid_cookie_trav/cookie/models/__init__.py
@@ -0,0 +1,12 @@
+from persistent.mapping import PersistentMapping
+
+
+class MyModel(PersistentMapping):
+ __parent__ = __name__ = None
+
+
+def appmaker(zodb_root):
+ if 'app_root' not in zodb_root:
+ app_root = MyModel()
+ zodb_root['app_root'] = app_root
+ return zodb_root['app_root']
diff --git a/pyramid_cookie_trav/cookie/pshell.py b/pyramid_cookie_trav/cookie/pshell.py
new file mode 100644
index 0000000..a7cfa6a
--- /dev/null
+++ b/pyramid_cookie_trav/cookie/pshell.py
@@ -0,0 +1,12 @@
+from . import models
+
+
+def setup(env):
+ request = env['request']
+
+ # start a transaction
+ request.tm.begin()
+
+ # inject some vars into the shell builtins
+ env['tm'] = request.tm
+ env['models'] = models
diff --git a/pyramid_cookie_trav/cookie/routes.py b/pyramid_cookie_trav/cookie/routes.py
new file mode 100644
index 0000000..3c0a379
--- /dev/null
+++ b/pyramid_cookie_trav/cookie/routes.py
@@ -0,0 +1,2 @@
+def includeme(config):
+ config.add_static_view('static', 'static', cache_max_age=3600)
diff --git a/pyramid_cookie_trav/cookie/static/pyramid-16x16.png b/pyramid_cookie_trav/cookie/static/pyramid-16x16.png
new file mode 100644
index 0000000..9792031
Binary files /dev/null and b/pyramid_cookie_trav/cookie/static/pyramid-16x16.png differ
diff --git a/pyramid_cookie_trav/cookie/static/pyramid.png b/pyramid_cookie_trav/cookie/static/pyramid.png
new file mode 100644
index 0000000..4ab837b
Binary files /dev/null and b/pyramid_cookie_trav/cookie/static/pyramid.png differ
diff --git a/pyramid_cookie_trav/cookie/static/theme.css b/pyramid_cookie_trav/cookie/static/theme.css
new file mode 100644
index 0000000..0f4b1a4
--- /dev/null
+++ b/pyramid_cookie_trav/cookie/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/pyramid_cookie_trav/cookie/templates/404.jinja2 b/pyramid_cookie_trav/cookie/templates/404.jinja2
new file mode 100644
index 0000000..aaf1241
--- /dev/null
+++ b/pyramid_cookie_trav/cookie/templates/404.jinja2
@@ -0,0 +1,8 @@
+{% extends "layout.jinja2" %}
+
+{% block content %}
+
+
Pyramid Starter project
+
404 Page Not Found
+
+{% endblock content %}
diff --git a/pyramid_cookie_trav/cookie/templates/layout.jinja2 b/pyramid_cookie_trav/cookie/templates/layout.jinja2
new file mode 100644
index 0000000..895ca46
--- /dev/null
+++ b/pyramid_cookie_trav/cookie/templates/layout.jinja2
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+ Cookiecutter Starter project for the Pyramid Web Framework
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 }})
+
+
+ {% block content %}
+
No content
+ {% endblock content %}
+
+
+
+
+
+ Copyright © Pylons Project
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pyramid_cookie_trav/cookie/templates/mytemplate.jinja2 b/pyramid_cookie_trav/cookie/templates/mytemplate.jinja2
new file mode 100644
index 0000000..f2e7283
--- /dev/null
+++ b/pyramid_cookie_trav/cookie/templates/mytemplate.jinja2
@@ -0,0 +1,8 @@
+{% extends "layout.jinja2" %}
+
+{% block content %}
+
+
Pyramid Starter project
+
Welcome to {{project}}, a Pyramid application generated by
Cookiecutter.
+
+{% endblock content %}
diff --git a/pyramid_cookie_trav/cookie/tests.py b/pyramid_cookie_trav/cookie/tests.py
new file mode 100644
index 0000000..67892b1
--- /dev/null
+++ b/pyramid_cookie_trav/cookie/tests.py
@@ -0,0 +1,18 @@
+import unittest
+
+from pyramid import testing
+
+
+class ViewTests(unittest.TestCase):
+ def setUp(self):
+ self.config = testing.setUp()
+
+ def tearDown(self):
+ testing.tearDown()
+
+ def test_my_view(self):
+ from .views.default import my_view
+ request = testing.DummyRequest()
+ info = my_view(request)
+ self.assertEqual(info['project'], 'cookie')
+
diff --git a/pyramid_cookie_trav/cookie/views/__init__.py b/pyramid_cookie_trav/cookie/views/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/pyramid_cookie_trav/cookie/views/default.py b/pyramid_cookie_trav/cookie/views/default.py
new file mode 100644
index 0000000..1b9c653
--- /dev/null
+++ b/pyramid_cookie_trav/cookie/views/default.py
@@ -0,0 +1,8 @@
+from pyramid.view import view_config
+
+from ..models import MyModel
+
+
+@view_config(context=MyModel, renderer='../templates/mytemplate.jinja2')
+def my_view(request):
+ return {'project': 'cookie'}
diff --git a/pyramid_cookie_trav/cookie/views/notfound.py b/pyramid_cookie_trav/cookie/views/notfound.py
new file mode 100644
index 0000000..69d6e28
--- /dev/null
+++ b/pyramid_cookie_trav/cookie/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 {}
diff --git a/pyramid_cookie_trav/development.ini b/pyramid_cookie_trav/development.ini
new file mode 100644
index 0000000..a97018c
--- /dev/null
+++ b/pyramid_cookie_trav/development.ini
@@ -0,0 +1,66 @@
+###
+# app configuration
+# https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
+###
+
+[app:main]
+use = egg:cookie
+
+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
+
+zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000
+
+retry.attempts = 3
+
+# By default, the toolbar only appears for clients from IP addresses
+# '127.0.0.1' and '::1'.
+# debugtoolbar.hosts = 127.0.0.1 ::1
+
+[pshell]
+setup = cookie.pshell.setup
+
+###
+# wsgi server configuration
+###
+
+[server:main]
+use = egg:waitress#main
+listen = localhost:6543
+
+###
+# logging configuration
+# https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
+###
+
+[loggers]
+keys = root, cookie
+
+[handlers]
+keys = console
+
+[formatters]
+keys = generic
+
+[logger_root]
+level = INFO
+handlers = console
+
+[logger_cookie]
+level = DEBUG
+handlers =
+qualname = cookie
+
+[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/pyramid_cookie_trav/production.ini b/pyramid_cookie_trav/production.ini
new file mode 100644
index 0000000..535c7df
--- /dev/null
+++ b/pyramid_cookie_trav/production.ini
@@ -0,0 +1,60 @@
+###
+# app configuration
+# https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
+###
+
+[app:main]
+use = egg:cookie
+
+pyramid.reload_templates = false
+pyramid.debug_authorization = false
+pyramid.debug_notfound = false
+pyramid.debug_routematch = false
+pyramid.default_locale_name = en
+
+zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000
+
+retry.attempts = 3
+
+[pshell]
+setup = cookie.pshell.setup
+
+###
+# wsgi server configuration
+###
+
+[server:main]
+use = egg:waitress#main
+listen = *:6543
+
+###
+# logging configuration
+# https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
+###
+
+[loggers]
+keys = root, cookie
+
+[handlers]
+keys = console
+
+[formatters]
+keys = generic
+
+[logger_root]
+level = WARN
+handlers = console
+
+[logger_cookie]
+level = WARN
+handlers =
+qualname = cookie
+
+[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/pyramid_cookie_trav/pytest.ini b/pyramid_cookie_trav/pytest.ini
new file mode 100644
index 0000000..9116b4c
--- /dev/null
+++ b/pyramid_cookie_trav/pytest.ini
@@ -0,0 +1,3 @@
+[pytest]
+testpaths = cookie
+python_files = test*.py
diff --git a/pyramid_cookie_trav/setup.py b/pyramid_cookie_trav/setup.py
new file mode 100644
index 0000000..57e1fab
--- /dev/null
+++ b/pyramid_cookie_trav/setup.py
@@ -0,0 +1,57 @@
+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 = [
+ 'plaster_pastedeploy',
+ 'pyramid',
+ 'pyramid_jinja2',
+ 'pyramid_debugtoolbar',
+ 'waitress',
+ 'pyramid_retry',
+ 'pyramid_tm',
+ 'pyramid_zodbconn',
+ 'transaction',
+ 'ZODB3',
+]
+
+tests_require = [
+ 'WebTest >= 1.3.1', # py3 compat
+ 'pytest >= 3.7.4',
+ 'pytest-cov',
+]
+
+setup(
+ name='cookie',
+ version='0.0',
+ description='cookie',
+ 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 = cookie:main',
+ ],
+ },
+)