Skip to content

Commit

Permalink
Merge pull request Pylons#3307 from Pylons/alembic-cookiecutter-alchemy
Browse files Browse the repository at this point in the history
Add Alembic support from alchemy cookiecutter
  • Loading branch information
mmerickel authored Aug 5, 2018
2 parents dc2eee4 + 6dd7a85 commit 76c066c
Show file tree
Hide file tree
Showing 107 changed files with 1,669 additions and 615 deletions.
3 changes: 3 additions & 0 deletions docs/glossary.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1206,3 +1206,6 @@ Glossary

context manager
A context manager is an object that defines the runtime context to be established when executing a :ref:`with <python:with>` statement in Python. The context manager handles the entry into, and the exit from, the desired runtime context for the execution of the block of code. Context managers are normally invoked using the ``with`` statement, but can also be used by directly invoking their methods. Pyramid adds context managers for :class:`pyramid.config.Configurator`, :meth:`pyramid.interfaces.IRouter.request_context`, :func:`pyramid.paster.bootstrap`, :func:`pyramid.scripting.prepare`, and :func:`pyramid.testing.testConfig`. See also the Python documentation for :ref:`With Statement Context Managers <python:context-managers>` and :pep:`343`.

Alembic
`Alembic <http://alembic.zzzcomputing.com/en/latest/>`_ is a lightweight database migration tool for usage with the SQLAlchemy Database Toolkit for Python.
8 changes: 4 additions & 4 deletions docs/tutorials/wiki2/authentication.rst
Original file line number Diff line number Diff line change
Expand Up @@ -122,15 +122,15 @@ Remember our goals:
* Only allow ``editor`` users and the page creator (possibly a ``basic`` user)
to edit pages.

Open the file ``tutorial/views/default.py`` and fix the following imports:
Open the file ``tutorial/views/default.py`` and fix the following import:

.. literalinclude:: src/authentication/tutorial/views/default.py
:lines: 5-13
:lines: 5-9
:lineno-match:
:emphasize-lines: 2,9
:emphasize-lines: 2
:language: python

Change the two highlighted lines.
Change the highlighted line.

In the same file, now edit the ``edit_page`` view function:

Expand Down
208 changes: 152 additions & 56 deletions docs/tutorials/wiki2/definingmodels.rst

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/tutorials/wiki2/definingviews.rst
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ edit it to look like the following:
.. literalinclude:: src/views/tutorial/views/default.py
:linenos:
:language: python
:emphasize-lines: 1-9,12-
:emphasize-lines: 1-9,14-

The highlighted lines need to be added or edited.

Expand Down
2 changes: 1 addition & 1 deletion docs/tutorials/wiki2/design.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Models
======

We'll be using an SQLite database to hold our wiki data, and we'll be using
:term:`SQLAlchemy` to access the data in this database.
:term:`SQLAlchemy` to access the data in this database. We will also use :term:`Alembic` for database migrations, including initialization of the SQLite database.

Within the database, we will define two tables:

Expand Down
243 changes: 160 additions & 83 deletions docs/tutorials/wiki2/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,143 @@ Testing requirements are defined in our project's ``setup.py`` file, in the ``te
:lines: 48-50


.. _initialize_db_wiki2:

Initialize and upgrade the database using Alembic
-------------------------------------------------

We use :term:`Alembic` to manage our database initialization and migrations.

Generate your first revision.

On UNIX
^^^^^^^

.. code-block:: bash
$ $VENV/bin/alembic -c development.ini revision --autogenerate -m "init"
On Windows
^^^^^^^^^^

.. code-block:: doscon
c:\tutorial> %VENV%\Scripts\alembic -c development.ini revision --autogenerate -m "init"
The output to your console should be something like this:

.. code-block:: text
2018-06-22 17:57:31,587 INFO [sqlalchemy.engine.base.Engine:1254][MainThread] SELECT CAST('test plain returns' AS VARCHAR(60)) AS anon_1
2018-06-22 17:57:31,587 INFO [sqlalchemy.engine.base.Engine:1255][MainThread] ()
2018-06-22 17:57:31,588 INFO [sqlalchemy.engine.base.Engine:1254][MainThread] SELECT CAST('test unicode returns' AS VARCHAR(60)) AS anon_1
2018-06-22 17:57:31,588 INFO [sqlalchemy.engine.base.Engine:1255][MainThread] ()
2018-06-22 17:57:31,589 INFO [sqlalchemy.engine.base.Engine:1151][MainThread] PRAGMA table_info("alembic_version")
2018-06-22 17:57:31,589 INFO [sqlalchemy.engine.base.Engine:1154][MainThread] ()
2018-06-22 17:57:31,590 INFO [sqlalchemy.engine.base.Engine:1151][MainThread] PRAGMA table_info("alembic_version")
2018-06-22 17:57:31,590 INFO [sqlalchemy.engine.base.Engine:1154][MainThread] ()
2018-06-22 17:57:31,590 INFO [sqlalchemy.engine.base.Engine:1151][MainThread]
CREATE TABLE alembic_version (
version_num VARCHAR(32) NOT NULL,
CONSTRAINT alembic_version_pkc PRIMARY KEY (version_num)
)
2018-06-22 17:57:31,591 INFO [sqlalchemy.engine.base.Engine:1154][MainThread] ()
2018-06-22 17:57:31,591 INFO [sqlalchemy.engine.base.Engine:722][MainThread] COMMIT
2018-06-22 17:57:31,594 INFO [sqlalchemy.engine.base.Engine:1151][MainThread] SELECT name FROM sqlite_master WHERE type='table' ORDER BY name
2018-06-22 17:57:31,594 INFO [sqlalchemy.engine.base.Engine:1154][MainThread] ()
Generating /<somepath>/tutorial/alembic/versions/20180622_bab5a278ce04.py ... done
Upgrade to that revision.

On UNIX
^^^^^^^

.. code-block:: bash
$ $VENV/bin/alembic -c development.ini upgrade head
On Windows
^^^^^^^^^^

.. code-block:: doscon
c:\tutorial> %VENV%\Scripts\alembic -c development.ini upgrade head
The output to your console should be something like this:

.. code-block:: text
2018-06-22 17:57:37,814 INFO [sqlalchemy.engine.base.Engine:1254][MainThread] SELECT CAST('test plain returns' AS VARCHAR(60)) AS anon_1
2018-06-22 17:57:37,814 INFO [sqlalchemy.engine.base.Engine:1255][MainThread] ()
2018-06-22 17:57:37,814 INFO [sqlalchemy.engine.base.Engine:1254][MainThread] SELECT CAST('test unicode returns' AS VARCHAR(60)) AS anon_1
2018-06-22 17:57:37,814 INFO [sqlalchemy.engine.base.Engine:1255][MainThread] ()
2018-06-22 17:57:37,816 INFO [sqlalchemy.engine.base.Engine:1151][MainThread] PRAGMA table_info("alembic_version")
2018-06-22 17:57:37,816 INFO [sqlalchemy.engine.base.Engine:1154][MainThread] ()
2018-06-22 17:57:37,817 INFO [sqlalchemy.engine.base.Engine:1151][MainThread] SELECT alembic_version.version_num
FROM alembic_version
2018-06-22 17:57:37,817 INFO [sqlalchemy.engine.base.Engine:1154][MainThread] ()
2018-06-22 17:57:37,817 INFO [sqlalchemy.engine.base.Engine:1151][MainThread] PRAGMA table_info("alembic_version")
2018-06-22 17:57:37,817 INFO [sqlalchemy.engine.base.Engine:1154][MainThread] ()
2018-06-22 17:57:37,819 INFO [sqlalchemy.engine.base.Engine:1151][MainThread]
CREATE TABLE models (
id INTEGER NOT NULL,
name TEXT,
value INTEGER,
CONSTRAINT pk_models PRIMARY KEY (id)
)
2018-06-22 17:57:37,820 INFO [sqlalchemy.engine.base.Engine:1154][MainThread] ()
2018-06-22 17:57:37,822 INFO [sqlalchemy.engine.base.Engine:722][MainThread] COMMIT
2018-06-22 17:57:37,824 INFO [sqlalchemy.engine.base.Engine:1151][MainThread] CREATE UNIQUE INDEX my_index ON models (name)
2018-06-22 17:57:37,824 INFO [sqlalchemy.engine.base.Engine:1154][MainThread] ()
2018-06-22 17:57:37,825 INFO [sqlalchemy.engine.base.Engine:722][MainThread] COMMIT
2018-06-22 17:57:37,825 INFO [sqlalchemy.engine.base.Engine:1151][MainThread] INSERT INTO alembic_version (version_num) VALUES ('bab5a278ce04')
2018-06-22 17:57:37,825 INFO [sqlalchemy.engine.base.Engine:1154][MainThread] ()
2018-06-22 17:57:37,825 INFO [sqlalchemy.engine.base.Engine:722][MainThread] COMMIT
.. _load_data_wiki2:

Load default data
-----------------

Load default data into the database using a :term:`console script`. Type the following command, making sure you are still in the ``tutorial`` directory (the directory with a ``development.ini`` in it):

On UNIX
^^^^^^^

.. code-block:: bash
$ $VENV/bin/initialize_tutorial_db development.ini
On Windows
^^^^^^^^^^

.. code-block:: doscon
c:\tutorial> %VENV%\Scripts\initialize_tutorial_db development.ini
The output to your console should be something like this:

.. code-block:: bash
2018-06-22 17:57:46,241 INFO [sqlalchemy.engine.base.Engine:1254][MainThread] SELECT CAST('test plain returns' AS VARCHAR(60)) AS anon_1
2018-06-22 17:57:46,241 INFO [sqlalchemy.engine.base.Engine:1255][MainThread] ()
2018-06-22 17:57:46,242 INFO [sqlalchemy.engine.base.Engine:1254][MainThread] SELECT CAST('test unicode returns' AS VARCHAR(60)) AS anon_1
2018-06-22 17:57:46,242 INFO [sqlalchemy.engine.base.Engine:1255][MainThread] ()
2018-06-22 17:57:46,243 INFO [sqlalchemy.engine.base.Engine:682][MainThread] BEGIN (implicit)
2018-06-22 17:57:46,244 INFO [sqlalchemy.engine.base.Engine:1151][MainThread] INSERT INTO models (name, value) VALUES (?, ?)
2018-06-22 17:57:46,245 INFO [sqlalchemy.engine.base.Engine:1154][MainThread] ('one', 1)
2018-06-22 17:57:46,246 INFO [sqlalchemy.engine.base.Engine:722][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
(``models``) and single record inside of that.


.. _sql_running_tests:

Run the tests
Expand Down Expand Up @@ -260,27 +397,28 @@ If successful, you will see output something like this:
.. code-block:: bash
======================== test session starts ========================
platform Python 3.6.0, pytest-3.0.5, py-1.4.31, pluggy-0.4.0
rootdir: /Users/stevepiercy/tutorial, inifile:
plugins: cov-2.4.0
platform Python 3.6.5, pytest-3.6.2, py-1.5.3, pluggy-0.6.0
rootdir: /<somepath>/tutorial, inifile: pytest.ini
plugins: cov-2.5.1
collected 2 items
tutorial/tests.py ..
------------------ coverage: platform Python 3.6.0 ------------------
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 2 33% 2-3
tutorial/scripts/__init__.py 0 0 100%
tutorial/scripts/initializedb.py 26 16 38% 22-25, 29-45
tutorial/views/__init__.py 0 0 100%
tutorial/views/default.py 12 0 100%
tutorial/views/notfound.py 4 2 50% 6-7
----------------------------------------------------------------
TOTAL 88 26 70%
------------------ coverage: platform Python 3.6.5 ------------------
Name Stmts Miss Cover Missing
-----------------------------------------------------------------
tutorial/__init__.py 8 6 25% 7-12
tutorial/models/__init__.py 24 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/initialize_db.py 24 24 0% 1-34
tutorial/views/__init__.py 0 0 100%
tutorial/views/default.py 12 0 100%
tutorial/views/notfound.py 4 4 0% 1-7
-----------------------------------------------------------------
TOTAL 88 37 58%
===================== 2 passed in 0.57 seconds ======================
Our package doesn't quite have 100% test coverage.
Expand Down Expand Up @@ -319,71 +457,6 @@ coverage.
``py.test -h`` to see its full set of options.


.. _initialize_db_wiki2:

Initializing the database
-------------------------

We need to use the ``initialize_tutorial_db`` :term:`console script` to
initialize our database.

.. note::

The ``initialize_tutorial_db`` command does not perform a migration, but
rather it simply creates missing tables and adds some dummy data. If you
already have a database, you should delete it before running
``initialize_tutorial_db`` again.

Type the following command, making sure you are still in the ``tutorial``
directory (the directory with a ``development.ini`` in it):

On UNIX
^^^^^^^

.. code-block:: bash
$ $VENV/bin/initialize_tutorial_db development.ini
On Windows
^^^^^^^^^^

.. code-block:: doscon
c:\tutorial> %VENV%\Scripts\initialize_tutorial_db development.ini
The output to your console should be something like this:

.. code-block:: bash
2016-12-18 21:30:08,675 INFO [sqlalchemy.engine.base.Engine:1235][MainThread] SELECT CAST('test plain returns' AS VARCHAR(60)) AS anon_1
2016-12-18 21:30:08,675 INFO [sqlalchemy.engine.base.Engine:1236][MainThread] ()
2016-12-18 21:30:08,676 INFO [sqlalchemy.engine.base.Engine:1235][MainThread] SELECT CAST('test unicode returns' AS VARCHAR(60)) AS anon_1
2016-12-18 21:30:08,676 INFO [sqlalchemy.engine.base.Engine:1236][MainThread] ()
2016-12-18 21:30:08,676 INFO [sqlalchemy.engine.base.Engine:1140][MainThread] PRAGMA table_info("models")
2016-12-18 21:30:08,676 INFO [sqlalchemy.engine.base.Engine:1143][MainThread] ()
2016-12-18 21:30:08,677 INFO [sqlalchemy.engine.base.Engine:1140][MainThread]
CREATE TABLE models (
id INTEGER NOT NULL,
name TEXT,
value INTEGER,
CONSTRAINT pk_models PRIMARY KEY (id)
)
2016-12-18 21:30:08,677 INFO [sqlalchemy.engine.base.Engine:1143][MainThread] ()
2016-12-18 21:30:08,678 INFO [sqlalchemy.engine.base.Engine:719][MainThread] COMMIT
2016-12-18 21:30:08,679 INFO [sqlalchemy.engine.base.Engine:1140][MainThread] CREATE UNIQUE INDEX my_index ON models (name)
2016-12-18 21:30:08,679 INFO [sqlalchemy.engine.base.Engine:1143][MainThread] ()
2016-12-18 21:30:08,679 INFO [sqlalchemy.engine.base.Engine:719][MainThread] COMMIT
2016-12-18 21:30:08,681 INFO [sqlalchemy.engine.base.Engine:679][MainThread] BEGIN (implicit)
2016-12-18 21:30:08,682 INFO [sqlalchemy.engine.base.Engine:1140][MainThread] INSERT INTO models (name, value) VALUES (?, ?)
2016-12-18 21:30:08,682 INFO [sqlalchemy.engine.base.Engine:1143][MainThread] ('one', 1)
2016-12-18 21:30:08,682 INFO [sqlalchemy.engine.base.Engine:719][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
(``models``).

.. _wiki2-start-the-application:

Start the application
Expand Down Expand Up @@ -445,6 +518,10 @@ assumptions:

- You are willing to use :term:`SQLAlchemy` for a database access tool.

- You are willing to use :term:`Alembic` for a database migrations tool.

- You are willing to use a :term:`console script` for a data loading tool.

- You are willing to use :term:`URL dispatch` to map URLs to code.

- You want to use zope.sqlalchemy_, pyramid_tm_, and the transaction_ packages
Expand Down
21 changes: 21 additions & 0 deletions docs/tutorials/wiki2/src/authentication/.gitignore
Original file line number Diff line number Diff line change
@@ -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
12 changes: 11 additions & 1 deletion docs/tutorials/wiki2/src/authentication/README.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,17 @@ Getting Started

env/bin/pip install -e ".[testing]"

- Configure the database.
- 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_tutorial_db development.ini

Expand Down
6 changes: 6 additions & 0 deletions docs/tutorials/wiki2/src/authentication/development.ini
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ auth.secret = seekrit
# wsgi server configuration
###

[alembic]
# path to migration scripts
script_location = tutorial/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
Expand Down
6 changes: 6 additions & 0 deletions docs/tutorials/wiki2/src/authentication/production.ini
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ auth.secret = real-seekrit
# wsgi server configuration
###

[alembic]
# path to migration scripts
script_location = tutorial/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
Expand Down
2 changes: 1 addition & 1 deletion docs/tutorials/wiki2/src/authentication/pytest.ini
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[pytest]
testpaths = tutorial
python_files = *.py
python_files = test*.py
Loading

0 comments on commit 76c066c

Please sign in to comment.