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

docs cookiecutter changes only - wiki2 #2883

Merged
merged 12 commits into from
Dec 24, 2016
10 changes: 5 additions & 5 deletions docs/tutorials/wiki/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -172,11 +172,11 @@ The console will show ``pip`` checking for packages and installing missing packa
WebTest-2.0.23 ZConfig-3.1.0 ZEO-5.0.4 ZODB-5.1.1 ZODB3-3.11.0 \
beautifulsoup4-4.5.1 coverage-4.2 mock-2.0.0 pbr-1.10.0 persistent-4.2.2 \
py-1.4.31 pyramid-1.7.3 pyramid-chameleon-0.3 pyramid-debugtoolbar-3.0.5 \
pyramid-mako-1.0.2 pyramid-tm-1.1.1 pyramid-zodbconn-0.7 pyramidtut \
pytest-3.0.5 pytest-cov-2.4.0 repoze.lru-0.6 six-1.10.0 transaction-2.0.3 \
translationstring-1.3 venusian-1.0 waitress-1.0.1 zc.lockfile-1.2.1 \
zdaemon-4.2.0 zodbpickle-0.6.0 zodburi-2.0 zope.deprecation-4.2.0 \
zope.interface-4.3.3
pyramid-mako-1.0.2 pyramid-tm-1.1.1 pyramid-zodbconn-0.7 pytest-3.0.5 \
pytest-cov-2.4.0 repoze.lru-0.6 six-1.10.0 transaction-2.0.3 \
translationstring-1.3 tutorial venusian-1.0 waitress-1.0.1 \
zc.lockfile-1.2.1 zdaemon-4.2.0 zodbpickle-0.6.0 zodburi-2.0 \
zope.deprecation-4.2.0 zope.interface-4.3.3

Testing requirements are defined in our project's ``setup.py`` file, in the ``tests_require`` and ``extras_require`` stanzas.

Expand Down
2 changes: 1 addition & 1 deletion docs/tutorials/wiki2/authentication.rst
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ Our authentication policy is expecting a new setting, ``auth.secret``. Open
the file ``development.ini`` and add the highlighted line below:

.. literalinclude:: src/authentication/development.ini
:lines: 18-20
:lines: 17-19
:emphasize-lines: 3
:lineno-match:
:language: ini
Expand Down
14 changes: 3 additions & 11 deletions docs/tutorials/wiki2/basiclayout.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
Basic Layout
============

The starter files generated by the ``alchemy`` scaffold are very basic, but
The starter files generated by the ``alchemy`` cookiecutter are very basic, but
they provide a good orientation for the high-level patterns common to most
:term:`URL dispatch`-based :app:`Pyramid` projects.

Expand All @@ -29,7 +29,6 @@ code:

.. literalinclude:: src/basiclayout/tutorial/__init__.py
:end-before: main
:linenos:
:lineno-match:
:language: py

Expand All @@ -38,7 +37,6 @@ the ``main`` function we've defined in our ``__init__.py``:

.. literalinclude:: src/basiclayout/tutorial/__init__.py
:pyobject: main
:linenos:
:lineno-match:
:language: py

Expand Down Expand Up @@ -179,7 +177,7 @@ decorator in order to create a view configuration within our application.
Without being processed by ``scan``, the decorator effectively does nothing.
``@view_config`` is inert without being detected via a :term:`scan`.

The sample ``my_view()`` created by the scaffold uses a ``try:`` and
The sample ``my_view()`` created by the cookiecutter uses a ``try:`` and
``except:`` clause to detect if there is a problem accessing the project
database and provide an alternate error response. That response will include
the text shown at the end of the file, which will be displayed in the browser
Expand All @@ -191,7 +189,7 @@ Content models with the ``models`` package

In an SQLAlchemy-based application, a *model* object is an object composed by
querying the SQL database. The ``models`` package is where the ``alchemy``
scaffold put the classes that implement our models.
cookiecutter put the classes that implement our models.

First, open ``tutorial/models/meta.py``, which should already contain the
following:
Expand Down Expand Up @@ -222,7 +220,6 @@ application's database schema.
.. literalinclude:: src/basiclayout/tutorial/models/meta.py
:lines: 15-16
:lineno-match:
:linenos:
:language: py

Next open ``tutorial/models/mymodel.py``, which should already contain the
Expand All @@ -239,7 +236,6 @@ we have defined one named ``MyModel`` in ``mymodel.py``:
.. literalinclude:: src/basiclayout/tutorial/models/mymodel.py
:pyobject: MyModel
:lineno-match:
:linenos:
:language: py

Our example model does not require an ``__init__`` method because SQLAlchemy
Expand Down Expand Up @@ -292,7 +288,6 @@ database engine using :func:`sqlalchemy.engine_from_config` from the
.. literalinclude:: src/basiclayout/tutorial/models/__init__.py
:pyobject: get_engine
:lineno-match:
:linenos:
:language: py

The function ``get_session_factory`` accepts an :term:`SQLAlchemy` database
Expand All @@ -303,7 +298,6 @@ used for creating sessions bound to the database engine.
.. literalinclude:: src/basiclayout/tutorial/models/__init__.py
:pyobject: get_session_factory
:lineno-match:
:linenos:
:language: py

The function ``get_tm_session`` registers a database session with a transaction
Expand All @@ -314,7 +308,6 @@ unless an exception is raised, in which case the transaction will be aborted.
.. literalinclude:: src/basiclayout/tutorial/models/__init__.py
:pyobject: get_tm_session
:lineno-match:
:linenos:
:language: py

Finally, we define an ``includeme`` function, which is a hook for use with
Expand All @@ -328,7 +321,6 @@ of an incoming request to our application.
.. literalinclude:: src/basiclayout/tutorial/models/__init__.py
:pyobject: includeme
:lineno-match:
:linenos:
:language: py

That's about all there is to it regarding models, views, and initialization
Expand Down
143 changes: 70 additions & 73 deletions docs/tutorials/wiki2/definingmodels.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
Defining the Domain Model
=========================

The first change we'll make to our stock ``pcreate``-generated application will
The first change we'll make to our stock cookiecutter-generated application will
be to define a wiki page :term:`domain model`.

.. note::
Expand All @@ -22,10 +22,10 @@ Declaring dependencies in our ``setup.py`` file

The models code in our application will depend on a package which is not a
dependency of the original "tutorial" application. The original "tutorial"
application was generated by the ``pcreate`` command; it doesn't know about our
application was generated by the cookiecutter; it doesn't know about our
custom application requirements.

We need to add a dependency, the ``bcrypt`` package, to our ``tutorial``
We need to add a dependency, the `bcrypt <https://pypi.python.org/pypi/bcrypt>`_ package, to our ``tutorial``
package's ``setup.py`` file by assigning this dependency to the ``requires``
parameter in the ``setup()`` function.

Expand All @@ -38,6 +38,10 @@ Open ``tutorial/setup.py`` and edit it to look like the following:

Only the highlighted line needs to be added.

.. note::

We are using the ``bcrypt`` package from PyPI to hash our passwords securely. There are other one-way hash algorithms for passwords if ``bcrypt`` is an issue on your system. Just make sure that it's an algorithm approved for storing passwords versus a generic one-way hash.


Running ``pip install -e .``
============================
Expand All @@ -53,31 +57,31 @@ On UNIX:

.. code-block:: bash

$ cd tutorial
$ $VENV/bin/pip install -e .
$ $VENV/bin/pip install -e .

On Windows:

.. code-block:: doscon

c:\pyramidtut> cd tutorial
c:\pyramidtut\tutorial> %VENV%\Scripts\pip install -e .
c:\tutorial> %VENV%\Scripts\pip install -e .

Success executing this command will end with a line to the console something
like this::
like the following.

Successfully installed bcrypt-2.0.0 cffi-1.5.2 pycparser-2.14 tutorial-0.0
.. code-block:: text

Successfully installed bcrypt-3.1.2 cffi-1.9.1 pycparser-2.17 tutorial


Remove ``mymodel.py``
---------------------
=====================

Let's delete the file ``tutorial/models/mymodel.py``. The ``MyModel`` class is
only a sample and we're not going to use it.


Add ``user.py``
---------------
===============

Create a new file ``tutorial/models/user.py`` with the following contents:

Expand All @@ -98,12 +102,12 @@ and ``role`` (all instances of :class:`sqlalchemy.schema.Column`). These will
map to columns in the ``users`` table. The ``id`` attribute will be the primary
key in the table. The ``name`` attribute will be a text column, each value of
which needs to be unique within the column. The ``password_hash`` is a nullable
text attribute that will contain a securely hashed password [1]_. Finally, the
text attribute that will contain a securely hashed password. Finally, the
``role`` text attribute will hold the role of the user.

There are two helper methods that will help us later when using the user
objects. The first is ``set_password`` which will take a raw password and
transform it using bcrypt_ into an irreversible representation, a process known
transform it using ``bcrypt`` into an irreversible representation, a process known
as "hashing". The second method, ``check_password``, will allow us to compare
the hashed value of the submitted password against the hashed value of the
password stored in the user's record in the database. If the two hashed values
Expand All @@ -116,7 +120,7 @@ authenticate as any user.


Add ``page.py``
---------------
===============

Create a new file ``tutorial/models/page.py`` with the following contents:

Expand All @@ -138,7 +142,7 @@ guaranteed that an instance of ``page`` will have a corresponding


Edit ``models/__init__.py``
---------------------------
===========================

Since we are using a package for our models, we also need to update our
``__init__.py`` file to ensure that the models are attached to the metadata.
Expand All @@ -155,12 +159,16 @@ Here we align our imports with the names of the models, ``Page`` and ``User``.


Edit ``scripts/initializedb.py``
--------------------------------
================================

We haven't looked at the details of this file yet, but within the ``scripts``
directory of your ``tutorial`` package is a file named ``initializedb.py``.
Code in this file is executed whenever we run the ``initialize_tutorial_db``
command, as we did in the installation step of this tutorial [2]_.
command, as we did in the installation step of this tutorial.

.. note::

The command is named ``initialize_tutorial_db`` because of the mapping defined in the ``[console_scripts]`` entry point of our project's ``setup.py`` file.

Since we've changed our model, we need to make changes to our
``initializedb.py`` script. In particular, we'll replace our import of
Expand All @@ -180,7 +188,7 @@ Only the highlighted lines need to be changed.


Installing the project and re-initializing the database
-------------------------------------------------------
=======================================================

Because our model has changed, and in order to reinitialize the database, we
need to rerun the ``initialize_tutorial_db`` command to pick up the changes
Expand All @@ -191,53 +199,53 @@ Success will look something like this:

.. code-block:: bash

2016-05-22 04:12:09,226 INFO [sqlalchemy.engine.base.Engine:1192][MainThread] SELECT CAST('test plain returns' AS VARCHAR(60)) AS anon_1
2016-05-22 04:12:09,226 INFO [sqlalchemy.engine.base.Engine:1193][MainThread] ()
2016-05-22 04:12:09,226 INFO [sqlalchemy.engine.base.Engine:1192][MainThread] SELECT CAST('test unicode returns' AS VARCHAR(60)) AS anon_1
2016-05-22 04:12:09,227 INFO [sqlalchemy.engine.base.Engine:1193][MainThread] ()
2016-05-22 04:12:09,227 INFO [sqlalchemy.engine.base.Engine:1097][MainThread] PRAGMA table_info("users")
2016-05-22 04:12:09,227 INFO [sqlalchemy.engine.base.Engine:1100][MainThread] ()
2016-05-22 04:12:09,228 INFO [sqlalchemy.engine.base.Engine:1097][MainThread] PRAGMA table_info("pages")
2016-05-22 04:12:09,228 INFO [sqlalchemy.engine.base.Engine:1100][MainThread] ()
2016-05-22 04:12:09,229 INFO [sqlalchemy.engine.base.Engine:1097][MainThread]
CREATE TABLE users (
id INTEGER NOT NULL,
name TEXT NOT NULL,
role TEXT NOT NULL,
password_hash TEXT,
CONSTRAINT pk_users PRIMARY KEY (id),
CONSTRAINT uq_users_name UNIQUE (name)
)


2016-05-22 04:12:09,229 INFO [sqlalchemy.engine.base.Engine:1100][MainThread] ()
2016-05-22 04:12:09,230 INFO [sqlalchemy.engine.base.Engine:686][MainThread] COMMIT
2016-05-22 04:12:09,230 INFO [sqlalchemy.engine.base.Engine:1097][MainThread]
CREATE TABLE pages (
id INTEGER NOT NULL,
name TEXT NOT NULL,
data TEXT NOT NULL,
creator_id INTEGER NOT NULL,
CONSTRAINT pk_pages PRIMARY KEY (id),
CONSTRAINT uq_pages_name UNIQUE (name),
CONSTRAINT fk_pages_creator_id_users FOREIGN KEY(creator_id) REFERENCES users (id)
)


2016-05-22 04:12:09,231 INFO [sqlalchemy.engine.base.Engine:1100][MainThread] ()
2016-05-22 04:12:09,231 INFO [sqlalchemy.engine.base.Engine:686][MainThread] COMMIT
2016-05-22 04:12:09,782 INFO [sqlalchemy.engine.base.Engine:646][MainThread] BEGIN (implicit)
2016-05-22 04:12:09,783 INFO [sqlalchemy.engine.base.Engine:1097][MainThread] INSERT INTO users (name, role, password_hash) VALUES (?, ?, ?)
2016-05-22 04:12:09,784 INFO [sqlalchemy.engine.base.Engine:1100][MainThread] ('editor', 'editor', b'$2b$12$K/WLVKRl5fMAb6UM58ueTetXlE3rlc5cRK5zFPimK598scXBR/xWC')
2016-05-22 04:12:09,784 INFO [sqlalchemy.engine.base.Engine:1097][MainThread] INSERT INTO users (name, role, password_hash) VALUES (?, ?, ?)
2016-05-22 04:12:09,784 INFO [sqlalchemy.engine.base.Engine:1100][MainThread] ('basic', 'basic', b'$2b$12$JfwLyCJGv3t.RTSmIrh3B.FKXRT9FevkAqafWdK5oq7Hl4mgAQORe')
2016-05-22 04:12:09,785 INFO [sqlalchemy.engine.base.Engine:1097][MainThread] INSERT INTO pages (name, data, creator_id) VALUES (?, ?, ?)
2016-05-22 04:12:09,785 INFO [sqlalchemy.engine.base.Engine:1100][MainThread] ('FrontPage', 'This is the front page', 1)
2016-05-22 04:12:09,786 INFO [sqlalchemy.engine.base.Engine:686][MainThread] COMMIT
2016-12-20 02:51:11,195 INFO [sqlalchemy.engine.base.Engine:1235][MainThread] SELECT CAST('test plain returns' AS VARCHAR(60)) AS anon_1
2016-12-20 02:51:11,195 INFO [sqlalchemy.engine.base.Engine:1236][MainThread] ()
2016-12-20 02:51:11,195 INFO [sqlalchemy.engine.base.Engine:1235][MainThread] SELECT CAST('test unicode returns' AS VARCHAR(60)) AS anon_1
2016-12-20 02:51:11,195 INFO [sqlalchemy.engine.base.Engine:1236][MainThread] ()
2016-12-20 02:51:11,196 INFO [sqlalchemy.engine.base.Engine:1140][MainThread] PRAGMA table_info("pages")
2016-12-20 02:51:11,196 INFO [sqlalchemy.engine.base.Engine:1143][MainThread] ()
2016-12-20 02:51:11,196 INFO [sqlalchemy.engine.base.Engine:1140][MainThread] PRAGMA table_info("users")
2016-12-20 02:51:11,197 INFO [sqlalchemy.engine.base.Engine:1143][MainThread] ()
2016-12-20 02:51:11,197 INFO [sqlalchemy.engine.base.Engine:1140][MainThread]
CREATE TABLE users (
id INTEGER NOT NULL,
name TEXT NOT NULL,
role TEXT NOT NULL,
password_hash TEXT,
CONSTRAINT pk_users PRIMARY KEY (id),
CONSTRAINT uq_users_name UNIQUE (name)
)


2016-12-20 02:51:11,197 INFO [sqlalchemy.engine.base.Engine:1143][MainThread] ()
2016-12-20 02:51:11,198 INFO [sqlalchemy.engine.base.Engine:719][MainThread] COMMIT
2016-12-20 02:51:11,199 INFO [sqlalchemy.engine.base.Engine:1140][MainThread]
CREATE TABLE pages (
id INTEGER NOT NULL,
name TEXT NOT NULL,
data TEXT NOT NULL,
creator_id INTEGER NOT NULL,
CONSTRAINT pk_pages PRIMARY KEY (id),
CONSTRAINT uq_pages_name UNIQUE (name),
CONSTRAINT fk_pages_creator_id_users FOREIGN KEY(creator_id) REFERENCES users (id)
)


2016-12-20 02:51:11,199 INFO [sqlalchemy.engine.base.Engine:1143][MainThread] ()
2016-12-20 02:51:11,200 INFO [sqlalchemy.engine.base.Engine:719][MainThread] COMMIT
2016-12-20 02:51:11,755 INFO [sqlalchemy.engine.base.Engine:679][MainThread] BEGIN (implicit)
2016-12-20 02:51:11,755 INFO [sqlalchemy.engine.base.Engine:1140][MainThread] INSERT INTO users (name, role, password_hash) VALUES (?, ?, ?)
2016-12-20 02:51:11,755 INFO [sqlalchemy.engine.base.Engine:1143][MainThread] ('editor', 'editor', '$2b$12$ds7h2Zb7.l6TEFup5h8f4ekA9GRfEpE1yQGDRvT9PConw73kKuupG')
2016-12-20 02:51:11,756 INFO [sqlalchemy.engine.base.Engine:1140][MainThread] INSERT INTO users (name, role, password_hash) VALUES (?, ?, ?)
2016-12-20 02:51:11,756 INFO [sqlalchemy.engine.base.Engine:1143][MainThread] ('basic', 'basic', '$2b$12$KgruXP5Vv7rikr6dGB3TF.flGXYpiE0Li9K583EVomjY.SYmQOsyi')
2016-12-20 02:51:11,757 INFO [sqlalchemy.engine.base.Engine:1140][MainThread] INSERT INTO pages (name, data, creator_id) VALUES (?, ?, ?)
2016-12-20 02:51:11,757 INFO [sqlalchemy.engine.base.Engine:1143][MainThread] ('FrontPage', 'This is the front page', 1)
2016-12-20 02:51:11,757 INFO [sqlalchemy.engine.base.Engine:719][MainThread] COMMIT


View the application in a browser
---------------------------------
=================================

We can't. At this point, our system is in a "non-runnable" state; we'll need
to change view-related files in the next chapter to be able to start the
Expand All @@ -250,14 +258,3 @@ your console that ends with this exception:
ImportError: cannot import name MyModel

This will also happen if you attempt to run the tests.

.. _bcrypt: https://pypi.python.org/pypi/bcrypt

.. [1] We are using the bcrypt_ package from PyPI to hash our passwords
securely. There are other one-way hash algorithms for passwords if
bcrypt is an issue on your system. Just make sure that it's an
algorithm approved for storing passwords versus a generic one-way hash.

.. [2] The command is named ``initialize_tutorial_db`` because of the mapping
defined in the ``[console_scripts]`` entry point of our project's
``setup.py`` file.
Loading