| @@ -0,0 +1,9 @@ | ||
| .installed.cfg | ||
| bin/ | ||
| bootstrap.py | ||
| eggs | ||
| parts/ | ||
| tasks.db | ||
| var/ | ||
| *.pyc | ||
| *.swp |
| @@ -0,0 +1,23 @@ | ||
| SHELL = /bin/bash | ||
| WGET = wget | ||
| PYTHON_VERSION := $(shell python -V 2>&1) | ||
| BOOTSTRAP_PY_URL = http://svn.zope.org/*checkout*/zc.buildout/branches/2/bootstrap/bootstrap.py | ||
| run: bin/python | ||
| bin/python tasks.py | ||
| bin/python: bin/buildout buildout.cfg | ||
| if [[ "$(PYTHON_VERSION)" == Python\ 3* ]]; then echo "*** Python 3 ***"; bin/buildout -c buildout-py3.cfg; else echo "*** Python 2 ***"; bin/buildout; fi | ||
| run-buildout: bin/buildout buildout.cfg | ||
| bin/buildout | ||
| bin/buildout: bootstrap.py | ||
| python bootstrap.py | ||
| bootstrap.py: | ||
| $(WGET) -O bootstrap.py $(BOOTSTRAP_PY_URL) | ||
| clean: | ||
| $(RM) -r bin bootstrap.py develop-eggs eggs parts tasks.db var .installed.cfg |
| @@ -0,0 +1,9 @@ | ||
| [buildout] | ||
| parts = | ||
| python | ||
| [python] | ||
| recipe = zc.recipe.egg | ||
| eggs = | ||
| pyramid | ||
| interpreter = python |
| @@ -0,0 +1,10 @@ | ||
| create table if not exists tasks ( | ||
| id integer primary key autoincrement, | ||
| name char(100) not null, | ||
| closed bool not null | ||
| ); | ||
| insert or ignore into tasks (id, name, closed) values (0, 'Start learning Pyramid', 0); | ||
| insert or ignore into tasks (id, name, closed) values (1, 'Do quick tutorial', 0); | ||
| insert or ignore into tasks (id, name, closed) values (2, 'Have some beer!', 0); | ||
| @@ -0,0 +1,75 @@ | ||
| body { | ||
| font-family: sans-serif; | ||
| font-size: 14px; | ||
| color: #3e4349; | ||
| } | ||
| h1, h2, h3, h4, h5, h6 { | ||
| font-family: Georgia; | ||
| color: #373839; | ||
| } | ||
| a { | ||
| color: #1b61d6; | ||
| text-decoration: none; | ||
| } | ||
| input { | ||
| font-size: 14px; | ||
| width: 400px; | ||
| border: 1px solid #bbbbbb; | ||
| padding: 5px; | ||
| } | ||
| .button { | ||
| font-size: 14px; | ||
| font-weight: bold; | ||
| width: auto; | ||
| background: #eeeeee; | ||
| padding: 5px 20px 5px 20px; | ||
| border: 1px solid #bbbbbb; | ||
| border-left: none; | ||
| border-right: none; | ||
| } | ||
| #flash, #notfound { | ||
| font-size: 16px; | ||
| width: 500px; | ||
| text-align: center; | ||
| background-color: #e1ecfe; | ||
| border-top: 2px solid #7a9eec; | ||
| border-bottom: 2px solid #7a9eec; | ||
| padding: 10px 20px 10px 20px; | ||
| } | ||
| #notfound { | ||
| background-color: #fbe3e4; | ||
| border-top: 2px solid #fbc2c4; | ||
| border-bottom: 2px solid #fbc2c4; | ||
| padding: 0 20px 30px 20px; | ||
| } | ||
| #tasks { | ||
| width: 500px; | ||
| } | ||
| #tasks li { | ||
| padding: 5px 0 5px 0; | ||
| border-bottom: 1px solid #bbbbbb; | ||
| } | ||
| #tasks li.last { | ||
| border-bottom: none; | ||
| } | ||
| #tasks .name { | ||
| width: 400px; | ||
| text-align: left; | ||
| display: inline-block; | ||
| } | ||
| #tasks .actions { | ||
| width: 80px; | ||
| text-align: right; | ||
| display: inline-block; | ||
| } |
| @@ -0,0 +1,109 @@ | ||
| import os | ||
| import logging | ||
| import sqlite3 | ||
| from pyramid.config import Configurator | ||
| from pyramid.events import NewRequest | ||
| from pyramid.events import subscriber | ||
| from pyramid.events import ApplicationCreated | ||
| from pyramid.exceptions import NotFound | ||
| from pyramid.httpexceptions import HTTPFound | ||
| from pyramid.session import UnencryptedCookieSessionFactoryConfig | ||
| from pyramid.view import view_config | ||
| from wsgiref.simple_server import make_server | ||
| logging.basicConfig() | ||
| log = logging.getLogger(__file__) | ||
| here = os.path.dirname(os.path.abspath(__file__)) | ||
| # views | ||
| @view_config(route_name='list', renderer='list.mako') | ||
| def list_view(request): | ||
| rs = request.db.execute("select id, name from tasks where closed = 0") | ||
| tasks = [dict(id=row[0], name=row[1]) for row in rs.fetchall()] | ||
| return {'tasks': tasks} | ||
| @view_config(route_name='new', renderer='new.mako') | ||
| def new_view(request): | ||
| if request.method == 'POST': | ||
| if request.POST.get('name'): | ||
| request.db.execute( | ||
| 'insert into tasks (name, closed) values (?, ?)', | ||
| [request.POST['name'], 0]) | ||
| request.db.commit() | ||
| request.session.flash('New task was successfully added!') | ||
| return HTTPFound(location=request.route_url('list')) | ||
| else: | ||
| request.session.flash('Please enter a name for the task!') | ||
| return {} | ||
| @view_config(route_name='close') | ||
| def close_view(request): | ||
| task_id = int(request.matchdict['id']) | ||
| request.db.execute("update tasks set closed = ? where id = ?", | ||
| (1, task_id)) | ||
| request.db.commit() | ||
| request.session.flash('Task was successfully closed!') | ||
| return HTTPFound(location=request.route_url('list')) | ||
| @view_config(context='pyramid.exceptions.NotFound', renderer='notfound.mako') | ||
| def notfound_view(request): | ||
| request.response.status = '404 Not Found' | ||
| return {} | ||
| # subscribers | ||
| @subscriber(NewRequest) | ||
| def new_request_subscriber(event): | ||
| request = event.request | ||
| settings = request.registry.settings | ||
| request.db = sqlite3.connect(settings['db']) | ||
| request.add_finished_callback(close_db_connection) | ||
| def close_db_connection(request): | ||
| request.db.close() | ||
| @subscriber(ApplicationCreated) | ||
| def application_created_subscriber(event): | ||
| log.warn('Initializing database...') | ||
| with open(os.path.join(here, 'schema.sql')) as f: | ||
| stmt = f.read() | ||
| settings = event.app.registry.settings | ||
| db = sqlite3.connect(settings['db']) | ||
| db.executescript(stmt) | ||
| db.commit() | ||
| if __name__ == '__main__': | ||
| # configuration settings | ||
| settings = {} | ||
| settings['reload_all'] = True | ||
| settings['debug_all'] = True | ||
| settings['db'] = os.path.join(here, 'tasks.db') | ||
| settings['mako.directories'] = os.path.join(here, 'templates') | ||
| # session factory | ||
| session_factory = UnencryptedCookieSessionFactoryConfig('itsaseekreet') | ||
| # configuration setup | ||
| config = Configurator(settings=settings, session_factory=session_factory) | ||
| # add mako templating | ||
| config.include('pyramid_mako') | ||
| # routes setup | ||
| config.add_route('list', '/') | ||
| config.add_route('new', '/new') | ||
| config.add_route('close', '/close/{id}') | ||
| # static view setup | ||
| config.add_static_view('static', os.path.join(here, 'static')) | ||
| # scan for @view_config and @subscriber decorators | ||
| config.scan() | ||
| # serve app | ||
| app = config.make_wsgi_app() | ||
| server = make_server('0.0.0.0', 8080, app) | ||
| server.serve_forever() |
| @@ -0,0 +1,32 @@ | ||
| # -*- coding: utf-8 -*- | ||
| <!DOCTYPE html> | ||
| <html> | ||
| <head> | ||
| <meta charset="utf-8"> | ||
| <title>Pyramid Task's List Tutorial</title> | ||
| <meta name="author" content="Pylons Project"> | ||
| <link rel="shortcut icon" href="/static/favicon.ico"> | ||
| <link rel="stylesheet" href="/static/style.css"> | ||
| </head> | ||
| <body> | ||
| % if request.session.peek_flash(): | ||
| <div id="flash"> | ||
| <% flash = request.session.pop_flash() %> | ||
| % for message in flash: | ||
| ${message}<br> | ||
| % endfor | ||
| </div> | ||
| % endif | ||
| <div id="page"> | ||
| ${next.body()} | ||
| </div> | ||
| </body> | ||
| </html> |
| @@ -0,0 +1,22 @@ | ||
| # -*- coding: utf-8 -*- | ||
| <%inherit file="layout.mako"/> | ||
| <h1>Task's List</h1> | ||
| <ul id="tasks"> | ||
| % if tasks: | ||
| % for task in tasks: | ||
| <li> | ||
| <span class="name">${task['name']}</span> | ||
| <span class="actions"> | ||
| [ <a href="${request.route_url('close', id=task['id'])}">close</a> ] | ||
| </span> | ||
| </li> | ||
| % endfor | ||
| % else: | ||
| <li>There are no open tasks</li> | ||
| % endif | ||
| <li class="last"> | ||
| <a href="${request.route_url('new')}">Add a new task</a> | ||
| </li> | ||
| </ul> |
| @@ -0,0 +1,9 @@ | ||
| # -*- coding: utf-8 -*- | ||
| <%inherit file="layout.mako"/> | ||
| <h1>Add a new task</h1> | ||
| <form action="${request.route_url('new')}" method="post"> | ||
| <input type="text" maxlength="100" name="name"> | ||
| <input type="submit" name="add" value="ADD" class="button"> | ||
| </form> |
| @@ -0,0 +1,7 @@ | ||
| # -*- coding: utf-8 -*- | ||
| <%inherit file="layout.mako"/> | ||
| <div id="notfound"> | ||
| <h1>404 - PAGE NOT FOUND</h1> | ||
| The page you're looking for isn't here. | ||
| </div> |