This is the Pyramid app for the Python Web Shootout.
Try it out here: http://demo.todo.sixfeetup.com
You can follow the instructions in the Pyramid docs on installation.
Once you have Python and virtualenv installed, you can do the following:
$ mkdir ~/.virtualenvs
$ cd ~/.virtualenvs
$ virtualenv -p python2.7 todopyramid
$ cd todopyramid
$ source bin/activate
This creates the new virtual environment, now you can install the app.
(todopyramid)$ cd ~/Desktop
(todopyramid)$ git clone https://github.com/indypy/todopyramid.git
(todopyramid)$ cd todopyramid
(todopyramid)$ pip install -r requirements.txt -e .
This gives us the end result of the finished app. If it is the first time you are running the app, you will need to initialize the database.
(todopyramid)$ initialize_todopyramid_db development.ini
It can now be started up by doing the following.
(todopyramid)$ pserve development.ini
Now go to http://localhost:6543 and enjoy!
The above install directions tell you how to get the finished application started. Here we will document how the app was created from scratch.
Started by creating a virtualenv and installing Pyramid into it.
(todopyramid)$ pip install pyramid
This gives us a starting point and the pcreate
command to create a new app. In this case, we used the alchemy
scaffold.
(todopyramid)$ cd ~/Desktop
(todopyramid)$ pcreate -s alchemy todopyramid
Since we are responsible developers, the first thing we should do is put this code into version control.
(todopyramid)$ cd todopyramid
(todopyramid)$ git init
(todopyramid)$ git add .
(todopyramid)$ git commit -m 'initial package from pcreate alchemy scaffold'
Before we start up the app for the first time, we need to install the new package that we've created, and all of its dependencies.
(todopyramid)$ python2.7 setup.py develop
Now that we've installed some more packages, we need to freeze the list of packages.
(todopyramid)$ pip freeze > requirements.txt
(todopyramid)$ git add requirements.txt
(todopyramid)$ git commit -m 'committing first version of requirements file'
Now let's initialize the database. In our example, we will be using SQLite.
(todopyramid)$ initialize_todopyramid_db development.ini
We don't want to check in the database, add it to the .gitignore
file.
(todopyramid)$ echo "todopyramid.sqlite" > .gitignore
(todopyramid)$ git add .gitignore
(todopyramid)$ git commit -m 'ignore the SQLite database'
Now we can start up the app and see what it looks like.
(todopyramid)$ pserve development.ini
This will include all the boilerplate code from the alchemy template.
For our purposes, we won't need some of the boilerplate code that has been added. We'll just get rid of it.
(todopyramid)$ git rm static/*
(todopyramid)$ touch static/.gitignore
(todopyramid)$ git add static/.gitignore
(todopyramid)$ git rm templates/*
(todopyramid)$ git commit -m 'removing boilerplate templates'
We've put a .gitignore
in the static
dir so that the directory stays in place. We'll add templates to the templates
dir soon, so it isn't necessary for that dir.
Now we are ready to start adding our customizations. First thing we want to do is add in Bootstrap to ease creation of layouts. Since we will be using Deform to create forms later on, we will use the deform_bootstrap package.
Add it to the setup.py
requires = [
# ...
'deform_bootstrap',
]
Then we need to pull in its dependencies (which includes Deform itself). Then update the requirements.txt
file.
(todopyramid)$ python2.7 setup.py develop
(todopyramid)$ pip freeze > requirements.txt
Then add the static resources to the __init__.py
```
config.add_static_view('deform_static', 'deform:static', cache_max_age=3600) config.add_static_view('deform_bootstrap_static', 'deform_bootstrap:static', cache_max_age=3600) ```
Now we need to get our template structure in place. We'll add a todopyramid/layouts.py
with the following (see the Creating a Custom UX for Pyramid tutorial for more details):
``` ifrom pyramid.renderers import get_renderer from pyramid.decorator import reify
class Layouts(object):
@reify
def global_template(self):
renderer = get_renderer("templates/global_layout.pt")
return renderer.implementation().macros['layout']
```
Add the global_layout.pt
with at least the following (look at the source code for the complete template):
```
<!-- Styles from Deform Bootstrap -->
<link rel="stylesheet" href="${request.static_url('deform_bootstrap:static/deform_bootstrap.css')}" type="text/css" media="screen" charset="utf-8" />
<link rel="stylesheet" href="${request.static_url('deform_bootstrap:static/chosen_bootstrap.css')}" type="text/css" media="screen" charset="utf-8" />
<link rel="stylesheet" href="${request.static_url('deform:static/css/ui-lightness/jquery-ui-1.8.11.custom.css')}" type="text/css" media="screen" charset="utf-8" />
```
Now we have to modify our boilerplate view to use the layout in todopyramid/views.py
, notice that we've also changed the view name and template name to reflect what this view does, showing the home
page.
``` from .layouts import Layouts
class ToDoViews(Layouts):
def __init__(self, context, request):
self.context = context
self.request = request
@view_config(route_name='home', renderer='templates/home.pt')
def home_view(request):
# view code here
return {}
```
Now we can add a todopyramid/templates/home.pt
to our app with the following
```
Welcome to the Pyramid version of the ToDo app.
Home
```
Now subsequent templates can be set up in the same manner.
Our app will need to authorize users in order to be able to add a ToDo list. Pyramid, having no opinions on the matter, leaves us with a myriad of options. One quick way is to utilize the Mozilla Persona login system. There just so happens to be a plugin for this called pyramid_persona
Following the documentation for the personas plugin, we add it to the dependencies of our app, build the latest version and include the plugin in our config.
We also override the default forbidden view in order to integrate a login form into our global template layout.
In order to keep up appearances, we add a custom Not Found view that integrates into our global layout. This is quite simple using the pyramid.view.notfound_view_config
Now that we have created the shell for our app, it is time to create some models. We will be utilizing SQLAlchemy in this case since it fits the needs of our application.
We will create a TodoItem
and Tag
model to start out with. This will give us the basis for our todo list.
Bumps mako from 0.7.3 to 1.2.2.
Sourced from mako's releases.
1.2.2
Released: Mon Aug 29 2022
bug
[bug] [lexer] Fixed issue in lexer where the regexp used to match tags would not correctly interpret quoted sections individually. While this parsing issue still produced the same expected tag structure later on, the mis-handling of quoted sections was also subject to a regexp crash if a tag had a large number of quotes within its quoted sections.
References: #366
1.2.1
Released: Thu Jun 30 2022
bug
[bug] [tests] Various fixes to the test suite in the area of exception message rendering to accommodate for variability in Python versions as well as Pygments.
References: #360
misc
[performance] Optimized some codepaths within the lexer/Python code generation process, improving performance for generation of templates prior to their being cached. Pull request courtesy Takuto Ikuta.
References: #361
1.2.0
Released: Thu Mar 10 2022
changed
[changed] [py3k] Corrected "universal wheel" directive in
setup.cfg
so that building a wheel does not target Python 2.References: #351
[changed] [py3k] The
bytestring_passthrough
template argument is removed, as this flag only applied to Python 2.
... (truncated)
Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase
.
Bumps waitress from 1.4.3 to 2.1.1.
Sourced from waitress's changelog.
2.1.1
Security Bugfix
- Waitress now validates that chunked encoding extensions are valid, and don't contain invalid characters that are not allowed. They are still skipped/not processed, but if they contain invalid data we no longer continue in and return a 400 Bad Request. This stops potential HTTP desync/HTTP request smuggling. Thanks to Zhang Zeyu for reporting this issue. See https://github.com/Pylons/waitress/security/advisories/GHSA-4f7p-27jc-3c36
Waitress now validates that the chunk length is only valid hex digits when parsing chunked encoding, and values such as
0x01
and+01
are no longer supported. This stops potential HTTP desync/HTTP request smuggling. Thanks to Zhang Zeyu for reporting this issue. See https://github.com/Pylons/waitress/security/advisories/GHSA-4f7p-27jc-3c36Waitress now validates that the Content-Length sent by a remote contains only digits in accordance with RFC7230 and will return a 400 Bad Request when the Content-Length header contains invalid data, such as
+10
which would previously get parsed as10
and accepted. This stops potential HTTP desync/HTTP request smuggling Thanks to Zhang Zeyu for reporting this issue. See https://github.com/Pylons/waitress/security/advisories/GHSA-4f7p-27jc-3c362.1.0
Python Version Support
Python 3.6 is no longer supported by Waitress
Python 3.10 is fully supported by Waitress
Bugfix
- ``wsgi.file_wrapper`` now sets the ``seekable``, ``seek``, and ``tell`` attributes from the underlying file if the underlying file is seekable. This allows WSGI middleware to implement things like range requests for example
See Pylons/waitress#359 and Pylons/waitress#363
- In Python 3
OSError
is no longer subscriptable, this caused failures on Windows attempting to loop to find an socket that would work for use in the trigger.</tr></table>
... (truncated)
9e0b8c8
Merge pull request from GHSA-4f7p-27jc-3c36b28c9e8
Prep for 2.1.1bd22869
Remove extraneous calls to .strip() in Chunked Encodingd9bdfa0
Validate chunk size in Chunked Encoding are HEXDIGd032a66
Error when receiving back Chunk Extension884bed1
Update tests to remove invalid chunked encoding chunk-size1f6059f
Be more strict in parsing Content-Lengthe75b0d9
Add new regular expressions for Chunked Encoding22c0394
Merge pull request #367 from Pylons/fixup/collect-wasyncore-testsdc15d9f
Make sure to collect all wasyncore testsDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase
.
Bumps ipython from 0.13.1 to 7.16.3.
Sourced from ipython's releases.
7.9.0
No release notes provided.
7.8.0
No release notes provided.
7.7.0
No release notes provided.
7.6.1
No release notes provided.
7.6.0
No release notes provided.
7.5.0
No release notes provided.
7.4.0
No release notes provided.
7.3.0
No release notes provided.
7.2.0
No release notes provided.
7.1.1
No release notes provided.
7.1.0
No release notes provided.
7.0.1
No release notes provided.
7.0.0
No release notes provided.
7.0.0-doc
No release notes provided.
7.0.0rc1
No release notes provided.
7.0.0b1
No release notes provided.
6.2.1
No release notes provided.
... (truncated)
d43c7c7
release 7.16.35fa1e40
Merge pull request from GHSA-pq7m-3gw7-gq5x8df8971
back to dev9f477b7
release 7.16.2138f266
bring back release helper from master branch5aa3634
Merge pull request #13341 from meeseeksmachine/auto-backport-of-pr-13335-on-7...bcae8e0
Backport PR #13335: What's new 7.16.28fcdcd3
Pin Jedi to <0.17.2.2486838
release 7.16.120bdc6f
fix conda buildDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase
.
Bumps sqlalchemy from 0.8.0b2 to 1.3.0.
Sourced from sqlalchemy's releases.
1.3.0
Released: March 4, 2019
[feature] [schema] Added new parameters
Table.resolve_fks
andMetaData.reflect.resolve_fks
which when set to False will disable the automatic reflection of related tables encountered inForeignKey
objects, which can both reduce SQL overhead for omitted tables as well as avoid tables that can't be reflected for database-specific reasons. TwoTable
objects present in the sameMetaData
collection can still refer to each other even if the reflection of the two tables occurred separately.References: #4517
[feature] [orm] The
Query.get()
method can now accept a dictionary of attribute keys and values as a means of indicating the primary key value to load; is particularly useful for composite primary keys. Pull request courtesy Sanjana S.References: #4316
[feature] [orm] A SQL expression can now be assigned to a primary key attribute for an ORM flush in the same manner as ordinary attributes as described in
flush_embedded_sql_expressions
where the expression will be evaulated and then returned to the ORM using RETURNING, or in the case of pysqlite, works using the cursor.lastrowid attribute.Requires either a database that supports RETURNING (e.g. Postgresql, Oracle, SQL Server) or pysqlite.References: #3133
[bug] [sql] The
Alias
class and related subclassesCTE
,Lateral
andTableSample
have been reworked so that it is not possible for a user to construct the objects directly. These constructs require that the standalone construction function or selectable-bound method be used to instantiate new objects.References: #4509
[engine] [feature] Revised the formatting for
StatementError
when stringified. Each error detail is broken up over multiple newlines instead of spaced out on a single line. Additionally, the SQL representation now stringifies the SQL statement rather than usingrepr()
, so that newlines are rendered as is. Pull request courtesy Nate Clark.References: #4500
Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase
.
I ported this project to run on Python 3.4. The site runs, but I can't log in. I suspect it has something to do with the newer versions of the dependencies I had to specify to get it to run on Python 3.4.
The version I converted to 3.4 is at https://github.com/christianmlong/todopyramid, on branch python3
The site runs, and when I click Sign In, it goes to the Persona sign-in page. However, after the Persona page is done, and I am back at the Todo app, I get two errors. See attached screenshots.
These screenshots are in the order that the errors occur - note the order is different on FF and Chrome.
The "Syntax error: Unexpected token <" error message looks like it's getting some html where it shouldn't be.
Steps to reproduce:
git clone [email protected]:christianmlong/todopyramid.git todopyramid34
cd todopyramid34
mkvirtualenv indypy34 --python=python3.4
git co python3
pip install -r requirements.txt
python setup.py develop
initialize_todopyramid_db development.ini
pserve development.ini
- Visit http://192.168.56.20:6543/
- Click on Sign In
- Complete the Persona sign in process
- When the Persona window closes, the error occurs.
This problem has been verified when running the server on Windows 8.1 and on Ubuntu 14.04.