Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Alembic support from alchemy cookiecutter #3307

Merged
merged 26 commits into from
Aug 5, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
63f2431
Update source files for installation step with new alembic support
stevepiercy Jun 23, 2018
8b43919
Update source files for basiclayout step for Alembic support
stevepiercy Jun 23, 2018
c8f3bf5
Add mention of migrations and Alembic in design and glossary.
stevepiercy Jun 23, 2018
487df3c
Synch up readmes with cookiecutter
stevepiercy Jun 25, 2018
a0cdd7b
add missing .gitignore
stevepiercy Jun 25, 2018
49620d9
Add Alembic and clarify console script in Installation step
stevepiercy Jun 26, 2018
9ce4986
Add omitted files to basiclayout step
stevepiercy Jun 26, 2018
6608630
Add alembic, correct name of init script in setup.py
stevepiercy Jun 26, 2018
beeee29
rename script to align with cookiecutter default
stevepiercy Jun 26, 2018
9f349cd
drop alpha status from pyramid requirement in setup.py
stevepiercy Jun 26, 2018
5b3f50e
switch to engine_from_config to be consistent with run_migrations_off…
stevepiercy Jun 27, 2018
89e464b
Add alembic directory to source in models step
stevepiercy Jun 27, 2018
03fc543
Add Alembic step and overview
stevepiercy Jun 28, 2018
0fa7506
First stab at updated db script
stevepiercy Jun 28, 2018
6986c6b
Modify sections for db script to align with Alembic workflow (WIP)
stevepiercy Jun 28, 2018
80ab8e7
Change import to module scope
stevepiercy Jun 28, 2018
c71eeae
Resynch src files to cookiecutter
stevepiercy Jun 29, 2018
178bf20
More synching of src to cc files
stevepiercy Jun 29, 2018
ed8004b
Add flake8
stevepiercy Jun 29, 2018
3b6264f
Gardening of definingmodels.rst
stevepiercy Jun 29, 2018
0d08c32
Synch up src files and update definingviews.rst
stevepiercy Jun 29, 2018
f63c10e
Synch up source files for authentication step
stevepiercy Jun 30, 2018
f0442aa
synch up linenos with source code
stevepiercy Jun 30, 2018
379b5ad
synch up source code in authorization step
stevepiercy Jun 30, 2018
1c36258
synch up source code in tests step
stevepiercy Jun 30, 2018
6dd7a85
use correct script name to fix tests
stevepiercy Jun 30, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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