formalchemy.ext.pyramid as moved

This commit is contained in:
Gael Pasgrimaud
2011-01-15 13:33:31 +01:00
commit ed87046427
46 changed files with 2232 additions and 0 deletions
+2
View File
@@ -0,0 +1,2 @@
*.pyc
*.pt.py
+4
View File
@@ -0,0 +1,4 @@
0.0
---
- Initial version
+4
View File
@@ -0,0 +1,4 @@
pyramid_formalchemy README
+260
View File
@@ -0,0 +1,260 @@
##############################################################################
#
# Copyright (c) 2006 Zope Foundation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Bootstrap a buildout-based project
Simply run this script in a directory containing a buildout.cfg.
The script accepts buildout command-line options, so you can
use the -c option to specify an alternate configuration file.
"""
import os, shutil, sys, tempfile, textwrap, urllib, urllib2, subprocess
from optparse import OptionParser
if sys.platform == 'win32':
def quote(c):
if ' ' in c:
return '"%s"' % c # work around spawn lamosity on windows
else:
return c
else:
quote = str
# See zc.buildout.easy_install._has_broken_dash_S for motivation and comments.
stdout, stderr = subprocess.Popen(
[sys.executable, '-Sc',
'try:\n'
' import ConfigParser\n'
'except ImportError:\n'
' print 1\n'
'else:\n'
' print 0\n'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
has_broken_dash_S = bool(int(stdout.strip()))
# In order to be more robust in the face of system Pythons, we want to
# run without site-packages loaded. This is somewhat tricky, in
# particular because Python 2.6's distutils imports site, so starting
# with the -S flag is not sufficient. However, we'll start with that:
if not has_broken_dash_S and 'site' in sys.modules:
# We will restart with python -S.
args = sys.argv[:]
args[0:0] = [sys.executable, '-S']
args = map(quote, args)
os.execv(sys.executable, args)
# Now we are running with -S. We'll get the clean sys.path, import site
# because distutils will do it later, and then reset the path and clean
# out any namespace packages from site-packages that might have been
# loaded by .pth files.
clean_path = sys.path[:]
import site
sys.path[:] = clean_path
for k, v in sys.modules.items():
if k in ('setuptools', 'pkg_resources') or (
hasattr(v, '__path__') and
len(v.__path__)==1 and
not os.path.exists(os.path.join(v.__path__[0],'__init__.py'))):
# This is a namespace package. Remove it.
sys.modules.pop(k)
is_jython = sys.platform.startswith('java')
setuptools_source = 'http://peak.telecommunity.com/dist/ez_setup.py'
distribute_source = 'http://python-distribute.org/distribute_setup.py'
# parsing arguments
def normalize_to_url(option, opt_str, value, parser):
if value:
if '://' not in value: # It doesn't smell like a URL.
value = 'file://%s' % (
urllib.pathname2url(
os.path.abspath(os.path.expanduser(value))),)
if opt_str == '--download-base' and not value.endswith('/'):
# Download base needs a trailing slash to make the world happy.
value += '/'
else:
value = None
name = opt_str[2:].replace('-', '_')
setattr(parser.values, name, value)
usage = '''\
[DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options]
Bootstraps a buildout-based project.
Simply run this script in a directory containing a buildout.cfg, using the
Python that you want bin/buildout to use.
Note that by using --setup-source and --download-base to point to
local resources, you can keep this script from going over the network.
'''
parser = OptionParser(usage=usage)
parser.add_option("-v", "--version", dest="version",
help="use a specific zc.buildout version")
parser.add_option("-d", "--distribute",
action="store_true", dest="use_distribute", default=False,
help="Use Distribute rather than Setuptools.")
parser.add_option("--setup-source", action="callback", dest="setup_source",
callback=normalize_to_url, nargs=1, type="string",
help=("Specify a URL or file location for the setup file. "
"If you use Setuptools, this will default to " +
setuptools_source + "; if you use Distribute, this "
"will default to " + distribute_source +"."))
parser.add_option("--download-base", action="callback", dest="download_base",
callback=normalize_to_url, nargs=1, type="string",
help=("Specify a URL or directory for downloading "
"zc.buildout and either Setuptools or Distribute. "
"Defaults to PyPI."))
parser.add_option("--eggs",
help=("Specify a directory for storing eggs. Defaults to "
"a temporary directory that is deleted when the "
"bootstrap script completes."))
parser.add_option("-t", "--accept-buildout-test-releases",
dest='accept_buildout_test_releases',
action="store_true", default=False,
help=("Normally, if you do not specify a --version, the "
"bootstrap script and buildout gets the newest "
"*final* versions of zc.buildout and its recipes and "
"extensions for you. If you use this flag, "
"bootstrap and buildout will get the newest releases "
"even if they are alphas or betas."))
parser.add_option("-c", None, action="store", dest="config_file",
help=("Specify the path to the buildout configuration "
"file to be used."))
options, args = parser.parse_args()
# if -c was provided, we push it back into args for buildout's main function
if options.config_file is not None:
args += ['-c', options.config_file]
if options.eggs:
eggs_dir = os.path.abspath(os.path.expanduser(options.eggs))
else:
eggs_dir = tempfile.mkdtemp()
if options.setup_source is None:
if options.use_distribute:
options.setup_source = distribute_source
else:
options.setup_source = setuptools_source
if options.accept_buildout_test_releases:
args.append('buildout:accept-buildout-test-releases=true')
args.append('bootstrap')
try:
import pkg_resources
import setuptools # A flag. Sometimes pkg_resources is installed alone.
if not hasattr(pkg_resources, '_distribute'):
raise ImportError
except ImportError:
ez_code = urllib2.urlopen(
options.setup_source).read().replace('\r\n', '\n')
ez = {}
exec ez_code in ez
setup_args = dict(to_dir=eggs_dir, download_delay=0)
if options.download_base:
setup_args['download_base'] = options.download_base
if options.use_distribute:
setup_args['no_fake'] = True
ez['use_setuptools'](**setup_args)
if 'pkg_resources' in sys.modules:
reload(sys.modules['pkg_resources'])
import pkg_resources
# This does not (always?) update the default working set. We will
# do it.
for path in sys.path:
if path not in pkg_resources.working_set.entries:
pkg_resources.working_set.add_entry(path)
cmd = [quote(sys.executable),
'-c',
quote('from setuptools.command.easy_install import main; main()'),
'-mqNxd',
quote(eggs_dir)]
if not has_broken_dash_S:
cmd.insert(1, '-S')
find_links = options.download_base
if not find_links:
find_links = os.environ.get('bootstrap-testing-find-links')
if find_links:
cmd.extend(['-f', quote(find_links)])
if options.use_distribute:
setup_requirement = 'distribute'
else:
setup_requirement = 'setuptools'
ws = pkg_resources.working_set
setup_requirement_path = ws.find(
pkg_resources.Requirement.parse(setup_requirement)).location
env = dict(
os.environ,
PYTHONPATH=setup_requirement_path)
requirement = 'zc.buildout'
version = options.version
if version is None and not options.accept_buildout_test_releases:
# Figure out the most recent final version of zc.buildout.
import setuptools.package_index
_final_parts = '*final-', '*final'
def _final_version(parsed_version):
for part in parsed_version:
if (part[:1] == '*') and (part not in _final_parts):
return False
return True
index = setuptools.package_index.PackageIndex(
search_path=[setup_requirement_path])
if find_links:
index.add_find_links((find_links,))
req = pkg_resources.Requirement.parse(requirement)
if index.obtain(req) is not None:
best = []
bestv = None
for dist in index[req.project_name]:
distv = dist.parsed_version
if _final_version(distv):
if bestv is None or distv > bestv:
best = [dist]
bestv = distv
elif distv == bestv:
best.append(dist)
if best:
best.sort()
version = best[-1].version
if version:
requirement = '=='.join((requirement, version))
cmd.append(requirement)
if is_jython:
import subprocess
exitcode = subprocess.Popen(cmd, env=env).wait()
else: # Windows prefers this, apparently; otherwise we would prefer subprocess
exitcode = os.spawnle(*([os.P_WAIT, sys.executable] + cmd + [env]))
if exitcode != 0:
sys.stdout.flush()
sys.stderr.flush()
print ("An error occurred when trying to install zc.buildout. "
"Look above this message for any errors that "
"were output by easy_install.")
sys.exit(exitcode)
ws.add_entry(eggs_dir)
ws.require(requirement)
import zc.buildout.buildout
zc.buildout.buildout.main(args)
if not options.eggs: # clean up temporary egg directory
shutil.rmtree(eggs_dir)
+25
View File
@@ -0,0 +1,25 @@
[buildout]
newest = false
extensions = gp.vcsdevelop
parts = eggs test
develop = . pyramidapp
[eggs]
recipe = zc.recipe.egg
eggs =
pyramid_formalchemy
pyramidapp
WebTest
PasteScript
Sphinx
[test]
recipe = zc.recipe.egg
eggs =
${eggs:eggs}
nose
initialization =
import os
os.chdir('pyramidapp')
scripts=
nosetests=nosetests
+44
View File
@@ -0,0 +1,44 @@
[app:pyramid_formalchemy]
use = egg:pyramid_formalchemy
reload_templates = true
debug_authorization = false
debug_notfound = false
debug_routematch = false
debug_templates = true
default_locale_name = en
[pipeline:main]
pipeline =
egg:WebError#evalerror
pyramid_formalchemy
[server:main]
use = egg:Paste#http
host = 0.0.0.0
port = 6543
# Begin logging configuration
[loggers]
keys = root
[handlers]
keys = console
[formatters]
keys = generic
[logger_root]
level = INFO
handlers = console
[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = NOTSET
formatter = generic
[formatter_generic]
format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s
# End logging configuration
+4
View File
@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
def include_formalchemy(config):
pass
+122
View File
@@ -0,0 +1,122 @@
<?xml version="1.0"?>
<configure xmlns="http://pylonshq.com/pyramid">
<include package="pyramid.includes" />
<static
name="fa_admin"
path="pyramid_formalchemy:static"
/>
<view
name=""
route_name="fa_admin"
context=".resources.AdminView"
view=".views.ModelView"
attr="models"
request_method="GET"
renderer="pyramid_formalchemy:templates/admin/models.pt"
/>
<view
name=""
route_name="fa_admin"
context=".resources.ModelListing"
view=".views.ModelView"
attr="listing"
request_method="GET"
renderer="pyramid_formalchemy:templates/admin/listing.pt"
/>
<view
name="new"
route_name="fa_admin"
context=".resources.ModelListing"
view=".views.ModelView"
attr="new"
request_method="GET"
renderer="pyramid_formalchemy:templates/admin/new.pt"
/>
<view
name=""
route_name="fa_admin"
context=".resources.ModelListing"
view=".views.ModelView"
attr="create"
request_method="POST"
renderer="pyramid_formalchemy:templates/admin/new.pt"
/>
<view
name="edit"
route_name="fa_admin"
context=".resources.ModelItem"
view=".views.ModelView"
attr="edit"
request_method="GET"
renderer="pyramid_formalchemy:templates/admin/edit.pt"
/>
<view
name="edit"
route_name="fa_admin"
context=".resources.ModelItem"
view=".views.ModelView"
attr="update"
request_method="POST"
renderer="pyramid_formalchemy:templates/admin/edit.pt"
/>
<view
name=""
route_name="fa_admin"
context=".resources.ModelItem"
view=".views.ModelView"
attr="update"
request_method="POST"
renderer="json"
/>
<view
name=""
route_name="fa_admin"
context=".resources.ModelItem"
view=".views.ModelView"
attr="update"
request_method="PUT"
renderer="json"
/>
<view
name="delete"
route_name="fa_admin"
context=".resources.ModelItem"
view=".views.ModelView"
attr="delete"
request_method="POST"
renderer="pyramid_formalchemy:templates/admin/edit.pt"
/>
<view
name=""
route_name="fa_admin"
context=".resources.ModelItem"
view=".views.ModelView"
attr="delete"
request_method="DELETE"
renderer="pyramid_formalchemy:templates/admin/edit.pt"
/>
<view
name=""
route_name="fa_admin"
context=".resources.ModelItem"
view=".views.ModelView"
attr="show"
request_method="GET"
renderer="pyramid_formalchemy:templates/admin/show.pt"
/>
</configure>
+39
View File
@@ -0,0 +1,39 @@
# -*- coding: utf-8 -*-
class AdminView(object):
def __init__(self, request):
self.request = request
request.model_name = None
request.model_id = None
request.format = 'html'
self.__parent__ = self.__name__ = None
def __getitem__(self, item):
if item in ('json',):
self.request.format = item
return self
model = ModelListing(self.request, item)
model.__parent__ = self
return model
class ModelListing(object):
def __init__(self, request, name):
self.request = request
request.model_name = name
self.__name__ = name
self.__parent__ = None
def __getitem__(self, item):
if item in ('json',):
self.request.format = item
return self
if item in ('new',):
raise KeyError()
model = ModelItem(self.request, item)
model.__parent__ = self
return model
class ModelItem(object):
def __init__(self, request, name):
request.model_id = name
self.__name__ = name
self.__parent__ = None
Binary file not shown.

After

Width:  |  Height:  |  Size: 323 B

+470
View File
@@ -0,0 +1,470 @@
/**
* Blue Box main CSS file
* @version 1.0.0
* @author Aaron D. Campbell http://xavisys.com/
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, font, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td {
border: 0;
font-family: inherit;
font-size: 100%;
font-style: inherit;
font-weight: inherit;
margin: 0;
outline: 0;
padding: 0;
vertical-align: baseline;
}
h1,h2,h3,h4,h5,h6 {
font-weight:bold;
}
h1 {
font-size:2em;
}
h2 {
font-size:1.5em;
}
h3 {
font-size:1.3em;
}
h4 {
font-size:1.1em;
}
h5 {
font-size:1em;
}
h6 {
font-size:.8em;
}
body {
background-color:#D5D6D7;
color:#333;
font:80% Verdana,"Trebuchet MS",Georgia,"Times New Roman",Times,serif;
margin:20px;
min-width:675px;
padding:0pt;
}
table {
margin:1em;
}
table, table tr {
border-collapse:collapse;
padding:0;
}
table th,
table td {
border:thin solid #D5D6D7;
border-collapse:collapse;
margin:0;
padding:0.2em 0.5em;
}
table th {
font-weight:bold;
background:#EFEFEF;
}
td a {
display:block;
}
tr.odd {
background:#EFEFEF;
}
p {
line-height:1.5em;
margin:1em 0;
}
#header {
background-color:#73A0C5;
border:1px solid #666;
border-bottom:none;
height:70px;
position:relative;
}
#title {
float:left;
margin:5px 0 0 1em;
}
#header h1 {
font-size:2em;
padding:0pt;
}
#header #tagline {
color:#DDD;
font-size:0.9em;
font-style:italic;
margin:0;
text-align:right;
}
#header h1,
#header h1 a,
#header h1 a:hover,
#header h1 a:visited {
color:#FFF;
text-decoration:none;
}
h1#header {
color: white;
height: 1.5em;
padding: 0.3em 1em;
}
h1#header a {
color: white;
}
.breadcrumb { float:right; font-size: 0.7em;}
#nav {
bottom:0;
position:absolute;
right:0;
}
#nav a {
background-color:#EFEFEF;
border:1px solid #666;
border-bottom:0;
color:#259;
font-size:1.2em;
font-weight:bold;
margin:0 .1em;
padding:.2em;
padding-bottom:0;
text-decoration:none;
}
#nav a:hover,
#nav a.current {
background-color:#FFF;
}
#content {
background-color:#FFF;
border:1px solid #666;
border-width:0 1px;
padding:1em;
}
#content ol {
margin-left:2em;
}
#content ul {
margin-left:1.5em;
}
#sidebar {
float:right;
margin:1em;
width:260px;
}
#sidebar .box p {
background-color:#F2F2F2;
margin:.5em;
}
#sidebar .box ul li {
border-bottom:1px solid #73A0C5;
list-style-type:none;
}
#sidebar .box ul li a {
display:block;
padding:.5em;
}
#sidebar .box label {
display:block;
float:left;
height:21px;
margin-right:10px;
width:70px;
}
#footer {
background-color:#EFEFEF;
border:1px solid #666;
border-top:none;
font-size:.8em;
padding:1em;
text-align:center;
}
#footer p {
margin:0;
}
a,
a:link {
color:#06C;
text-decoration:none;
}
a:visited {
color:#147;
}
a:hover,
a:active {
color:#147;
text-decoration:underline;
}
blockquote,
code {
background-color:#F2F2F2;
border-left:4px solid #73A0C5;
display:block;
font-style:oblique;
line-height:20px;
margin:0 1em;
padding:0 1em;
}
code {
white-space:pre;
}
.box{
border:1px solid #999;
margin:0 0 1em 0;
overflow:auto;
}
.box p,
.box ul,
.box ol,
.box div.cont,
.box form {
margin:.5em;
}
.box h1,
.box h2,
.box h3,
.box h4,
.box h5,
.box h6 {
background-color:#73A0C5;
display:block;
padding:0 5px;
color:white;
}
.more {
display:block;
font-size:.8em;
text-align:right;
}
/*********
* Forms *
*********/
.admin-flash,
fieldset {
color:#777;
margin-top:15px;
padding:10px;
}
.admin-flash {
background:#EFEFEF;
margin-bottom:15px;
font-weight:bold;
}
.message,
fieldset,
input,
button,
fieldset textarea,
fieldset select {
border:1px solid #F5F5F5;
border-left-color:#DDD;
border-top-color:#DDD;
}
legend {
color:#73A0C5;
font-weight:bold;
padding:5px 10px;
}
input,
button,
fieldset textarea,
fieldset select {
color:#777;
font:90% Verdana;
padding:4px;
}
fieldset textarea {
width:430px;
}
option {
padding:0 10px 0 5px;
}
fieldset label,
fieldset p.label {
color:#777;
text-align:right;
width:145px;
}
fieldset label {
float:left;
margin:5px 0;
margin-right:10px;
}
fieldset p {
margin:0;
}
fieldset div {
padding:5px 0;
position:relative;
}
fieldset div div {
margin:0;
}
fieldset p.label {
left:0;
position:absolute;
}
.radio {
margin-left:160px;
}
.radio label,
.radio input {
background:none;
border:none;
display:inline;
float:none;
vertical-align:middle;
width:auto;
}
.radio div {
clear:none;
white-space:nowrap;
}
#sidebar form {
margin:0 0 1em 0;
}
.submit,
#sidebar .submit {
text-align:right;
}
.ui-widget-link,
.submit input,
#sidebar .submit input {
background-color:#F9F9F9;
border:1px solid #F5F5F5;
border-left-color:#DDD;
border-top-color:#DDD;
cursor:pointer;
padding:0 21px;
text-transform:lowercase;
width:auto;
}
.ui-widget-link input {
border:0px;
background:transparent;
}
a.ui-widget-link {
color:#777777;
font-family:Verdana;
}
.ui-widget-link {
cursor:pointer;
margin-right:0.3em;
}
td form { text-align:center;}
td input.ui-icon {
background-color:transparent;
border:0px;
width:16px;
height: 0px;
overflow:hidden;
padding-bottom:13px;
cursor:pointer;
}
.ui-icon-pencil {
background-image: url(./edit.png);
}
.ui-icon-circle-close {
background-image: url(./delete.png);
}
#sidebar input {
border:1px solid #DDD;
border-bottom-color:#F5F5F5;
border-right-color:#F5F5F5;
width:100%;
}
#sidebar label {
height:auto;
margin-bottom:0;
width:auto;
}
.button {
width:auto;
}
.form_controls {
margin-left:155px;
}
.icon {
display:block;
height:0px;
padding-top:16px;
width:16px;
overflow:hidden;
}
input.icon {
border:none;
width:16px;
height:16px;
padding:0;
cursor:pointer;
}
#pager {
text-align: center;
margin-top: 0.5em;
}
#pager a, #pager .pager_curpage {
padding: 0 0.2em;
border:thin solid #114477;
background: #73A0C5;
color: white;
}
#pager a:hover, #pager .pager_curpage {
text-decoration:none;
background:white;
color:#114477;
}
/*****************************/
Binary file not shown.

After

Width:  |  Height:  |  Size: 247 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 574 B

@@ -0,0 +1,13 @@
<html metal:use-macro="main.macros['master']">
<body>
<div metal:fill-slot="main">
<form action="" method="POST" enctype="multipart/form-data">
<div tal:content="structure fs.render()" />
<input type="hidden" name="_method" value="PUT" />
<div metal:use-macro="main.macros['buttons']">
</div>
</form>
</div>
</body>
</html>
@@ -0,0 +1,15 @@
<html metal:use-macro="main.macros['master']">
<body>
<div metal:fill-slot="main">
<div class="ui-pager" tal:content="structure pager" />
<table class="layout-grid" tal:content="structure fs.render()" />
<p>
<a class="ui-widget-header ui-widget-link ui-corner-all"
tal:attributes="href request.route_url('fa_admin', traverse='%s/new' % request.model_name)">
<span class="ui-icon ui-icon-circle-plus"></span>
${F_('New')} ${model_name}
</a>
</p>
</div>
</body>
</html>
@@ -0,0 +1,34 @@
<html metal:define-macro="master">
<head>
<title tal:content="request.model_name or 'root'"></title>
<link rel="stylesheet" tal:attributes="href request.static_url('pyramid_formalchemy:static/admin.css')"></link>
</head>
<body>
<div id="content" class="ui-admin ui-widget">
<h1 id="header" class="ui-widget-header ui-corner-all">
<div class="breadcrumb">
<tal:repeat tal:repeat="item breadcrumb">
<a tal:attributes="href python:item[0]"
tal:content="python:item[1]" />
<span tal:condition="not repeat.item.end">/</span>
</tal:repeat>
</div>
<div tal:content="request.model_name or 'root'"></div>
</h1>
<div metal:define-slot="main">
</div>
</div>
</body>
</html>
<div metal:define-macro="buttons">
<p class="fa_field">
<a class="ui-widget-header ui-widget-link ui-widget-button ui-corner-all" href="#">
<input type="submit" value="${F_('Save')}" />
</a>
<a class="ui-widget-header ui-widget-link ui-corner-all"
tal:attributes="href request.route_url('fa_admin', traverse=request.model_name)">
<span class="ui-icon ui-icon-circle-arrow-w"></span>
${F_('Cancel')}
</a>
</p>
</div>
@@ -0,0 +1,12 @@
<html metal:use-macro="main.macros['master']">
<body>
<div metal:fill-slot="main">
<div tal:repeat="item models">
<div>
<a tal:attributes="href request.route_url('fa_admin', traverse=item)"
tal:content="item"></a>
</div>
</div>
</div>
</body>
</html>
@@ -0,0 +1,15 @@
<html metal:use-macro="main.macros['master']">
<body>
<div metal:fill-slot="main">
<form method="POST" enctype="multipart/form-data"
tal:attributes="action request.route_url('fa_admin', traverse=request.model_name)"
>
<div tal:content="structure fs.render()" />
<div metal:use-macro="main.macros['buttons']">
</div>
</form>
</div>
</body>
</html>
@@ -0,0 +1,96 @@
{{if template_engine == 'mako'}}
# -*- coding: utf-8 -*-
<%!
from formalchemy.ext.pylons.controller import model_url
from pylons import url
%>
<%def name="h1(title, href=None)">
<h1 id="header" class="ui-widget-header ui-corner-all">
%if breadcrumb:
<div class="breadcrumb">
/${'/'.join([u and '<a href="%s">%s</a>' % (u,n.lower()) or n.lower() for u,n in breadcrumb])|n}
</div>
%endif
%if href:
<a href="${href}">${title.title()}</a>
%else:
${title.title()}
%endif
</h1>
</%def>
<%def name="buttons()">
<p class="fa_field">
<a class="ui-widget-header ui-widget-link ui-widget-button ui-corner-all" href="#">
<input type="submit" value="${F_('Save')}" />
</a>
<a class="ui-widget-header ui-widget-link ui-corner-all" href="${model_url(collection_name)}">
<span class="ui-icon ui-icon-circle-arrow-w"></span>
${F_('Cancel')}
</a>
</p>
</%def>
<html>
<head>
<title>
${collection_name.title()}
</title>
<link rel="stylesheet" type="text/css" href="${url('fa_static', path_info='/admin.css')}" />
</head>
<body>
<div id="content" class="ui-admin ui-widget">
%if isinstance(models, dict):
<h1 id="header" class="ui-widget-header ui-corner-all">${F_('Models')}</h1>
%for name in sorted(models):
<p>
<a class="ui-state-default ui-corner-all" href="${models[name]}">${name}</a>
</p>
%endfor
%elif is_grid:
${h1(model_name)}
<div class="ui-pager">
${pager|n}
</div>
<table class="layout-grid">
${fs.render()|n}
</table>
<p>
<a class="ui-widget-header ui-widget-link ui-corner-all" href="${model_url('new_%s' % member_name)}">
<span class="ui-icon ui-icon-circle-plus"></span>
${F_('New')} ${model_name}
</a>
</p>
%else:
${h1(model_name, href=model_url(collection_name))}
%if action == 'show':
<table>
${fs.render()|n}
</table>
<p class="fa_field">
<a class="ui-widget-header ui-widget-link ui-corner-all" href="${model_url('edit_%s' % member_name, id=id)}">
<span class="ui-icon ui-icon-pencil"></span>
${F_('Edit')}
</a>
</p>
%elif action == 'edit':
<form action="${model_url(member_name, id=id)}" method="POST" enctype="multipart/form-data">
${fs.render()|n}
<input type="hidden" name="_method" value="PUT" />
${buttons()}
</form>
%else:
<form action="${model_url(collection_name)}" method="POST" enctype="multipart/form-data">
${fs.render()|n}
${buttons()}
</form>
%endif
%endif
</div>
<script type="text/javascript">
var icons = document.getElementsByClassName('ui-icon')
for (var i = 0; i < icons.length-1; i++) {
icons[i].setAttribute('value', ' ');
}
</script>
</body></html>
{{endif}}
@@ -0,0 +1,10 @@
<html metal:use-macro="main.macros['master']">
<body>
<div metal:fill-slot="main">
<div tal:content="structure fs.render()" />
<div metal:use-macro="main.macros['buttons']">
</div>
</div>
</body>
</html>
@@ -0,0 +1,76 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal">
<head>
<title>The Pyramid Web Application Development Framework</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<meta name="keywords" content="python web application" />
<meta name="description" content="pyramid web application" />
<link rel="shortcut icon" href="${request.static_url('pyramid_formalchemy:static/favicon.ico')}" />
<link rel="stylesheet" href="${request.static_url('pyramid_formalchemy:static/pylons.css')}" type="text/css" media="screen" charset="utf-8" />
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Nobile:regular,italic,bold,bolditalic&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
<!--[if lte IE 6]>
<link rel="stylesheet" href="${request.static_url('pyramid_formalchemy:static/ie6.css')}" type="text/css" media="screen" charset="utf-8" />
<![endif]-->
</head>
<body>
<div id="wrap">
<div id="top">
<div class="top align-center">
<div><img src="${request.static_url('pyramid_formalchemy:static/pyramid.png')}" width="750" height="169" alt="pyramid"/></div>
</div>
</div>
<div id="middle">
<div class="middle align-center">
<p class="app-welcome">
Welcome to <span class="app-name">${project}</span>, an application generated by<br/>
the Pyramid web application development framework.
</p>
</div>
</div>
<div id="bottom">
<div class="bottom">
<div id="left" class="align-right">
<h2>Search documentation</h2>
<form method="get" action="http://docs.pylonshq.com/pyramid/dev/search.html">
<input type="text" id="q" name="q" value="" />
<input type="submit" id="x" value="Go" />
</form>
</div>
<div id="right" class="align-left">
<h2>Pyramid links</h2>
<ul class="links">
<li>
<a href="http://pylonshq.com">Pylons Website</a>
</li>
<li>
<a href="http://docs.pylonshq.com/pyramid/dev/#narrative-documentation">Narrative Documentation</a>
</li>
<li>
<a href="http://docs.pylonshq.com/pyramid/dev/#api-documentation">API Documentation</a>
</li>
<li>
<a href="http://docs.pylonshq.com/pyramid/dev/#tutorials">Tutorials</a>
</li>
<li>
<a href="http://docs.pylonshq.com/pyramid/dev/#change-history">Change History</a>
</li>
<li>
<a href="http://docs.pylonshq.com/pyramid/dev/#sample-applications">Sample Applications</a>
</li>
<li>
<a href="http://docs.pylonshq.com/pyramid/dev/#support-and-development">Support and Development</a>
</li>
<li>
<a href="irc://irc.freenode.net#pyramid">IRC Channel</a>
</li>
</ul>
</div>
</div>
</div>
</div>
<div id="footer">
<div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div>
</div>
</body>
</html>
+458
View File
@@ -0,0 +1,458 @@
# -*- coding: utf-8 -*-
import os
from webhelpers.paginate import Page
from sqlalchemy.orm import class_mapper, object_session
from formalchemy.fields import _pk
from formalchemy.fields import _stringify
from formalchemy import Grid, FieldSet
from formalchemy.i18n import get_translator
from formalchemy.fields import Field
from formalchemy import fatypes
from pyramid.view import view_config
from pyramid.renderers import render
from pyramid.renderers import get_renderer
from pyramid import httpexceptions as exc
try:
from formalchemy.ext.couchdb import Document
except ImportError:
Document = None
try:
import simplejson as json
except ImportError:
import json
class Session(object):
"""A abstract class to implement other backend than SA"""
def add(self, record):
"""add a record"""
def update(self, record):
"""update a record"""
def delete(self, record):
"""delete a record"""
def commit(self):
"""commit transaction"""
class ModelView(object):
"""A RESTful view bound to a model"""
engine = prefix_name = None
pager_args = dict(link_attr={'class': 'ui-pager-link ui-state-default ui-corner-all'},
curpage_attr={'class': 'ui-pager-curpage ui-state-highlight ui-corner-all'})
def __init__(self, context, request):
self.context = context
self.request = request
self.settings = request.registry.settings
self.model = self.settings['fa.models']
self.forms = self.settings.get('fa.forms', None)
self.FieldSet = self.settings.get('fa.fieldset', FieldSet)
self.Grid = self.settings.get('fa.grid', Grid)
@property
def model_name(self):
"""return ``model_name`` from ``pylons.routes_dict``"""
try:
return self.request.model_name
except AttributeError:
return None
def route_url(self, *args):
return self.request.route_url('fa_admin', traverse='/'.join([str(a) for a in args]))
def Session(self):
"""return a Session object. You **must** override this."""
return self.settings['fa.session_factory']()
def models(self, **kwargs):
"""Models index page"""
request = self.request
models = {}
if isinstance(self.model, list):
for model in self.model:
key = model.__name__
models[key] = self.route_url(key, request.format)
else:
for key, obj in self.model.__dict__.iteritems():
if not key.startswith('_'):
if Document is not None:
try:
if issubclass(obj, Document):
models[key] = self.route_url(key, request.format)
continue
except:
pass
try:
class_mapper(obj)
except:
continue
if not isinstance(obj, type):
continue
models[key] = self.route_url(key, request.format)
return self.render(models=models)
def get_model(self):
if isinstance(self.model, list):
for model in self.model:
if model.__name__ == self.model_name:
return model
elif hasattr(self.model, self.model_name):
return getattr(self.model, self.model_name)
raise exc.HTTPNotFound(description='model %s not found' % self.model_name)
def get_fieldset(self, id):
if self.forms and hasattr(self.forms, self.model_name):
fs = getattr(self.forms, self.model_name)
fs.engine = fs.engine or self.engine
return id and fs.bind(self.get(id)) or fs
raise KeyError(self.model_name)
def get_add_fieldset(self):
if self.forms and hasattr(self.forms, '%sAdd' % self.model_name):
fs = getattr(self.forms, '%sAdd' % self.model_name)
fs.engine = fs.engine or self.engine
return fs
return self.get_fieldset(id=None)
def get_grid(self):
model_name = self.model_name
if self.forms and hasattr(self.forms, '%sGrid' % model_name):
g = getattr(self.forms, '%sGrid' % model_name)
g.engine = g.engine or self.engine
g.readonly = True
self.update_grid(g)
return g
raise KeyError(self.model_name)
def sync(self, fs, id=None):
"""sync a record. If ``id`` is None add a new record else save current one.
Default is::
S = self.Session()
if id:
S.merge(fs.model)
else:
S.add(fs.model)
S.commit()
"""
S = self.Session()
if id:
S.merge(fs.model)
else:
S.add(fs.model)
def breadcrumb(self, fs=None, **kwargs):
"""return items to build the breadcrumb"""
items = []
request = self.request
model_name = request.model_name
id = request.model_id
items.append((self.route_url(), 'root'))
if self.model_name:
items.append((self.route_url(model_name), model_name))
if id and hasattr(fs.model, '__unicode__'):
items.append((self.route_url(model_name, id), u'%s' % fs.model))
elif id:
items.append((self.route_url(model_name, id), id))
return items
def render(self, **kwargs):
"""render the form as html or json"""
request = self.request
if request.format != 'html':
meth = getattr(self, 'render_%s_format' % request.format, None)
if meth is not None:
return meth(**kwargs)
else:
return exc.HTTPNotfound()
kwargs.update(
main = get_renderer('pyramid_formalchemy:templates/admin/master.pt').implementation(),
model_name=self.model_name,
breadcrumb=self.breadcrumb(**kwargs),
F_=get_translator().gettext)
return kwargs
def render_grid(self, **kwargs):
"""render the grid as html or json"""
return self.render(is_grid=True, **kwargs)
def render_json_format(self, fs=None, **kwargs):
request = self.request
request.override_renderer = 'json'
if fs:
try:
fields = fs.jsonify()
except AttributeError:
fields = dict([(field.renderer.name, field.model_value) for field in fs.render_fields.values()])
data = dict(fields=fields)
pk = _pk(fs.model)
if pk:
data['item_url'] = request.route_url('fa_admin', traverse='%s/json/%s' % (self.model_name, pk))
else:
data = {}
data.update(kwargs)
return data
def render_xhr_format(self, fs=None, **kwargs):
response.content_type = 'text/html'
if fs is not None:
if 'field' in request.GET:
field_name = request.GET.get('field')
fields = fs.render_fields
if field_name in fields:
field = fields[field_name]
return field.render()
else:
return exc.HTTPNotfound()
return fs.render()
return ''
def get_page(self, **kwargs):
"""return a ``webhelpers.paginate.Page`` used to display ``Grid``.
Default is::
S = self.Session()
query = S.query(self.get_model())
kwargs = request.environ.get('pylons.routes_dict', {})
return Page(query, page=int(request.GET.get('page', '1')), **kwargs)
"""
S = self.Session()
def get_page_url(page, partial=None):
url = "%s?page=%s" % (self.request.path, page)
if partial:
url += "&partial=1"
return url
options = dict(collection=S.query(self.get_model()),
page=int(self.request.GET.get('page', '1')),
url=get_page_url)
options.update(kwargs)
collection = options.pop('collection')
return Page(collection, **options)
def get(self, id=None):
"""return correct record for ``id`` or a new instance.
Default is::
S = self.Session()
model = self.get_model()
if id:
model = S.query(model).get(id)
else:
model = model()
return model or abort(404)
"""
S = self.Session()
model = self.get_model()
if id:
model = S.query(model).get(id)
if model:
return model
raise exc.HTTPNotFound()
def get_fieldset(self, id=None):
"""return a ``FieldSet`` object bound to the correct record for ``id``.
Default is::
fs = self.FieldSet(self.get(id))
fs.engine = fs.engine or self.engine
return fs
"""
if self.forms and hasattr(self.forms, self.model_name):
fs = getattr(self.forms, self.model_name)
fs.engine = fs.engine or self.engine
return id and fs.bind(self.get(id)) or fs
fs = self.FieldSet(self.get(id))
fs.engine = fs.engine or self.engine
return fs
def get_add_fieldset(self):
"""return a ``FieldSet`` used for add form.
Default is::
fs = self.get_fieldset()
for field in fs.render_fields.itervalues():
if field.is_readonly():
del fs[field.name]
return fs
"""
fs = self.get_fieldset()
for field in fs.render_fields.itervalues():
if field.is_readonly():
del fs[field.name]
return fs
def get_grid(self):
"""return a Grid object
Default is::
grid = self.Grid(self.get_model())
grid.engine = self.engine
self.update_grid(grid)
return grid
"""
model_name = self.model_name
if self.forms and hasattr(self.forms, '%sGrid' % model_name):
g = getattr(self.forms, '%sGrid' % model_name)
g.engine = g.engine or self.engine
g.readonly = True
self.update_grid(g)
return g
grid = self.Grid(self.get_model())
grid.engine = self.engine
self.update_grid(grid)
return grid
def update_grid(self, grid):
"""Add edit and delete buttons to ``Grid``"""
try:
grid.edit
except AttributeError:
def edit_link():
return lambda item: '''
<form action="%(url)s" method="GET" class="ui-grid-icon ui-widget-header ui-corner-all">
<input type="submit" class="ui-grid-icon ui-icon ui-icon-pencil" title="%(label)s" value="%(label)s" />
</form>
''' % dict(url=self.route_url(self.model_name, _pk(item), 'edit'),
label=get_translator().gettext('edit'))
def delete_link():
return lambda item: '''
<form action="%(url)s" method="POST" class="ui-grid-icon ui-state-error ui-corner-all">
<input type="submit" class="ui-icon ui-icon-circle-close" title="%(label)s" value="%(label)s" />
</form>
''' % dict(url=self.route_url(self.model_name, _pk(item), 'delete'),
label=get_translator().gettext('delete'))
grid.append(Field('edit', fatypes.String, edit_link()))
grid.append(Field('delete', fatypes.String, delete_link()))
grid.readonly = True
def listing(self, **kwargs):
"""listing page"""
page = self.get_page()
fs = self.get_grid()
fs = fs.bind(instances=page)
fs.readonly = True
if self.request.format == 'json':
values = []
request = self.request
for item in page:
pk = _pk(item)
fs._set_active(item)
value = dict(id=pk,
item_url=self.route_url(request.model_name, pk))
if 'jqgrid' in request.GET:
fields = [_stringify(field.render_readonly()) for field in fs.render_fields.values()]
value['cell'] = [pk] + fields
else:
value.update(dict([(field.key, field.model_value) for field in fs.render_fields.values()]))
values.append(value)
return self.render_json_format(rows=values,
records=len(values),
total=page.page_count,
page=page.page)
if 'pager' not in kwargs:
pager = page.pager(**self.pager_args)
else:
pager = kwargs.pop('pager')
return self.render_grid(fs=fs, id=None, pager=pager)
def create(self):
"""REST api"""
request = self.request
S = self.Session()
fs = self.get_add_fieldset()
if request.format == 'json' and request.method == 'PUT':
data = json.load(request.body_file)
else:
data = request.POST
try:
fs = fs.bind(data=data, session=S)
except:
# non SA forms
fs = fs.bind(self.get_model(), data=data, session=S)
if fs.validate():
fs.sync()
self.sync(fs)
S.flush()
if request.format == 'html':
if request.is_xhr:
response.content_type = 'text/plain'
return ''
return exc.HTTPFound(
location=self.route_url(request.model_name))
else:
fs.rebind(fs.model, data=None)
return self.render(fs=fs)
return self.render(fs=fs, action='new', id=None)
def delete(self, **kwargs):
"""REST api"""
request = self.request
id = request.model_id
record = self.get(id)
if record:
S = self.Session()
S.delete(record)
if request.format == 'html':
if request.is_xhr:
response = Response()
response.content_type = 'text/plain'
return response
return exc.HTTPFound(location=self.route_url(request.model_name))
return self.render(id=id)
def show(self):
"""REST api"""
id = self.request.model_id
fs = self.get_fieldset(id=id)
fs.readonly = True
return self.render(fs=fs, action='show', id=id)
def new(self, **kwargs):
"""REST api"""
fs = self.get_add_fieldset()
fs = fs.bind(session=self.Session())
return self.render(fs=fs, action='new', id=None)
def edit(self, id=None, **kwargs):
"""REST api"""
id = self.request.model_id
fs = self.get_fieldset(id)
return self.render(fs=fs, action='edit', id=id)
def update(self, **kwargs):
"""REST api"""
request = self.request
S = self.Session()
id = request.model_id
fs = self.get_fieldset(id)
if not request.POST:
raise ValueError(request.POST)
fs = fs.bind(data=request.POST)
if fs.validate():
fs.sync()
self.sync(fs, id)
S.flush()
if request.format == 'html':
if request.is_xhr:
response.content_type = 'text/plain'
return ''
return exc.HTTPFound(
location=self.route_url(request.model_name, _pk(fs.model)))
else:
return self.render(fs=fs, status=0)
if request.format == 'html':
return self.render(fs=fs, action='edit', id=id)
else:
return self.render(fs=fs, status=1)
+4
View File
@@ -0,0 +1,4 @@
0.0
---
- Initial version
+4
View File
@@ -0,0 +1,4 @@
pyramidapp README
+54
View File
@@ -0,0 +1,54 @@
[app:pyramidapp]
use = egg:pyramidapp
reload_templates = true
debug_authorization = false
debug_notfound = false
debug_routematch = false
debug_templates = true
default_locale_name = en
sqlalchemy.url = sqlite:///%(here)s/pyramidapp.db
[pipeline:main]
pipeline =
egg:WebError#evalerror
egg:repoze.tm2#tm
pyramidapp
[server:main]
use = egg:Paste#http
host = 0.0.0.0
port = 6543
# Begin logging configuration
[loggers]
keys = root, sqlalchemy
[handlers]
keys = console
[formatters]
keys = generic
[logger_root]
level = INFO
handlers = console
[logger_sqlalchemy]
level = INFO
handlers =
qualname = sqlalchemy.engine
# "level = INFO" logs SQL queries.
# "level = DEBUG" logs SQL queries and results.
# "level = WARN" logs neither. (Recommended for production systems.)
[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = NOTSET
formatter = generic
[formatter_generic]
format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s
# End logging configuration
Binary file not shown.
+25
View File
@@ -0,0 +1,25 @@
from pyramid.config import Configurator
from sqlalchemy import engine_from_config
from pyramidapp.models import initialize_sql
def main(global_config, **settings):
""" This function returns a Pyramid WSGI application.
"""
engine = engine_from_config(settings, 'sqlalchemy.')
initialize_sql(engine)
config = Configurator(settings=settings)
config.add_static_view('static', 'pyramidapp:static')
config.add_route('home', '/', view='pyramidapp.views.my_view',
view_renderer='templates/mytemplate.pt')
config.load_zcml('pyramid_formalchemy:configure.zcml')
config.add_route('fa_admin', '/admin/*traverse',
factory='pyramid_formalchemy.resources.AdminView')
config.registry.settings.update({
'fa.models': config.maybe_dotted('pyramidapp.models'),
'fa.forms': config.maybe_dotted('pyramidapp.forms'),
'fa.session_factory': config.maybe_dotted('pyramidapp.models.DBSession'),
})
return config.make_wsgi_app()
+2
View File
@@ -0,0 +1,2 @@
# -*- coding: utf-8 -*-
+47
View File
@@ -0,0 +1,47 @@
import transaction
from sqlalchemy import Column
from sqlalchemy import Integer
from sqlalchemy import Unicode
from sqlalchemy.exc import IntegrityError
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import scoped_session
from sqlalchemy.orm import sessionmaker
from zope.sqlalchemy import ZopeTransactionExtension
DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
Base = declarative_base()
class MyModel(Base):
__tablename__ = 'models'
id = Column(Integer, primary_key=True)
name = Column(Unicode(255), unique=True)
value = Column(Integer)
class Foo(Base):
__tablename__ = 'foo'
id = Column(Integer, primary_key=True)
bar = Column(Unicode(255))
def populate():
session = DBSession()
model = MyModel(name=u'root',value=55)
session.add(model)
session.flush()
for i in range(50):
model = MyModel(name=u'root%i' % i,value=i)
session.add(model)
session.flush()
transaction.commit()
def initialize_sql(engine):
DBSession.configure(bind=engine)
Base.metadata.bind = engine
Base.metadata.create_all(engine)
try:
populate()
except IntegrityError:
DBSession.rollback()
+3
View File
@@ -0,0 +1,3 @@
class Root(object):
def __init__(self, request):
self.request = request
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 333 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 B

+8
View File
@@ -0,0 +1,8 @@
* html img,
* html .png{position:relative;behavior:expression((this.runtimeStyle.behavior="none")&&(this.pngSet?this.pngSet=true:(this.nodeName == "IMG" && this.src.toLowerCase().indexOf('.png')>-1?(this.runtimeStyle.backgroundImage = "none",
this.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + this.src + "',sizingMethod='image')",
this.src = "static/transparent.gif"):(this.origBg = this.origBg? this.origBg :this.currentStyle.backgroundImage.toString().replace('url("','').replace('")',''),
this.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + this.origBg + "',sizingMethod='crop')",
this.runtimeStyle.backgroundImage = "none")),this.pngSet=true)
);}
#wrap{display:table;height:100%}
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

+65
View File
@@ -0,0 +1,65 @@
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td{margin:0;padding:0;border:0;outline:0;font-size:100%;/* 16px */
vertical-align:baseline;background:transparent;}
body{line-height:1;}
ol,ul{list-style:none;}
blockquote,q{quotes:none;}
blockquote:before,blockquote:after,q:before,q:after{content:'';content:none;}
:focus{outline:0;}
ins{text-decoration:none;}
del{text-decoration:line-through;}
table{border-collapse:collapse;border-spacing:0;}
sub{vertical-align:sub;font-size:smaller;line-height:normal;}
sup{vertical-align:super;font-size:smaller;line-height:normal;}
ul,menu,dir{display:block;list-style-type:disc;margin:1em 0;padding-left:40px;}
ol{display:block;list-style-type:decimal-leading-zero;margin:1em 0;padding-left:40px;}
li{display:list-item;}
ul ul,ul ol,ul dir,ul menu,ul dl,ol ul,ol ol,ol dir,ol menu,ol dl,dir ul,dir ol,dir dir,dir menu,dir dl,menu ul,menu ol,menu dir,menu menu,menu dl,dl ul,dl ol,dl dir,dl menu,dl dl{margin-top:0;margin-bottom:0;}
ol ul,ul ul,menu ul,dir ul,ol menu,ul menu,menu menu,dir menu,ol dir,ul dir,menu dir,dir dir{list-style-type:circle;}
ol ol ul,ol ul ul,ol menu ul,ol dir ul,ol ol menu,ol ul menu,ol menu menu,ol dir menu,ol ol dir,ol ul dir,ol menu dir,ol dir dir,ul ol ul,ul ul ul,ul menu ul,ul dir ul,ul ol menu,ul ul menu,ul menu menu,ul dir menu,ul ol dir,ul ul dir,ul menu dir,ul dir dir,menu ol ul,menu ul ul,menu menu ul,menu dir ul,menu ol menu,menu ul menu,menu menu menu,menu dir menu,menu ol dir,menu ul dir,menu menu dir,menu dir dir,dir ol ul,dir ul ul,dir menu ul,dir dir ul,dir ol menu,dir ul menu,dir menu menu,dir dir menu,dir ol dir,dir ul dir,dir menu dir,dir dir dir{list-style-type:square;}
.hidden{display:none;}
p{line-height:1.5em;}
h1{font-size:1.75em;line-height:1.7em;font-family:helvetica,verdana;}
h2{font-size:1.5em;line-height:1.7em;font-family:helvetica,verdana;}
h3{font-size:1.25em;line-height:1.7em;font-family:helvetica,verdana;}
h4{font-size:1em;line-height:1.7em;font-family:helvetica,verdana;}
html,body{width:100%;height:100%;}
body{margin:0;padding:0;background-color:#ffffff;position:relative;font:16px/24px "Nobile","Lucida Grande",Lucida,Verdana,sans-serif;}
a{color:#1b61d6;text-decoration:none;}
a:hover{color:#e88f00;text-decoration:underline;}
body h1,
body h2,
body h3,
body h4,
body h5,
body h6{font-family:"Neuton","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:normal;color:#373839;font-style:normal;}
#wrap{min-height:100%;}
#header,#footer{width:100%;color:#ffffff;height:40px;position:absolute;text-align:center;line-height:40px;overflow:hidden;font-size:12px;vertical-align:middle;}
#header{background:#000000;top:0;font-size:14px;}
#footer{bottom:0;background:#000000 url(footerbg.png) repeat-x 0 top;position:relative;margin-top:-40px;clear:both;}
.header,.footer{width:750px;margin-right:auto;margin-left:auto;}
.wrapper{width:100%}
#top,#top-small,#bottom{width:100%;}
#top{color:#000000;height:230px;background:#ffffff url(headerbg.png) repeat-x 0 top;position:relative;}
#top-small{color:#000000;height:60px;background:#ffffff url(headerbg.png) repeat-x 0 top;position:relative;}
#bottom{color:#222;background-color:#ffffff;}
.top,.top-small,.middle,.bottom{width:750px;margin-right:auto;margin-left:auto;}
.top{padding-top:40px;}
.top-small{padding-top:10px;}
#middle{width:100%;height:100px;background:url(middlebg.png) repeat-x;border-top:2px solid #ffffff;border-bottom:2px solid #b2b2b2;}
.app-welcome{margin-top:25px;}
.app-name{color:#000000;font-weight:bold;}
.bottom{padding-top:50px;}
#left{width:350px;float:left;padding-right:25px;}
#right{width:350px;float:right;padding-left:25px;}
.align-left{text-align:left;}
.align-right{text-align:right;}
.align-center{text-align:center;}
ul.links{margin:0;padding:0;}
ul.links li{list-style-type:none;font-size:14px;}
form{border-style:none;}
fieldset{border-style:none;}
input{color:#222;border:1px solid #ccc;font-family:sans-serif;font-size:12px;line-height:16px;}
input[type=text],input[type=password]{width:205px;}
input[type=submit]{background-color:#ddd;font-weight:bold;}
/*Opera Fix*/
body:before{content:"";height:100%;float:left;width:0;margin-top:-32767px;}
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 B

@@ -0,0 +1,76 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal">
<head>
<title>The Pyramid Web Application Development Framework</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<meta name="keywords" content="python web application" />
<meta name="description" content="pyramid web application" />
<link rel="shortcut icon" href="${request.static_url('pyramidapp:static/favicon.ico')}" />
<link rel="stylesheet" href="${request.static_url('pyramidapp:static/pylons.css')}" type="text/css" media="screen" charset="utf-8" />
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Nobile:regular,italic,bold,bolditalic&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
<!--[if lte IE 6]>
<link rel="stylesheet" href="${request.static_url('pyramidapp:static/ie6.css')}" type="text/css" media="screen" charset="utf-8" />
<![endif]-->
</head>
<body>
<div id="wrap">
<div id="top">
<div class="top align-center">
<div><img src="${request.static_url('pyramidapp:static/pyramid.png')}" width="750" height="169" alt="pyramid"/></div>
</div>
</div>
<div id="middle">
<div class="middle align-center">
<p class="app-welcome">
Welcome to <span class="app-name">${project}</span>, an application generated by<br/>
the Pyramid web application development framework.
</p>
</div>
</div>
<div id="bottom">
<div class="bottom">
<div id="left" class="align-right">
<h2>Search documentation</h2>
<form method="get" action="http://docs.pylonshq.com/pyramid/dev/search.html">
<input type="text" id="q" name="q" value="" />
<input type="submit" id="x" value="Go" />
</form>
</div>
<div id="right" class="align-left">
<h2>Pyramid links</h2>
<ul class="links">
<li>
<a href="http://pylonshq.com">Pylons Website</a>
</li>
<li>
<a href="http://docs.pylonshq.com/pyramid/dev/#narrative-documentation">Narrative Documentation</a>
</li>
<li>
<a href="http://docs.pylonshq.com/pyramid/dev/#api-documentation">API Documentation</a>
</li>
<li>
<a href="http://docs.pylonshq.com/pyramid/dev/#tutorials">Tutorials</a>
</li>
<li>
<a href="http://docs.pylonshq.com/pyramid/dev/#change-history">Change History</a>
</li>
<li>
<a href="http://docs.pylonshq.com/pyramid/dev/#sample-applications">Sample Applications</a>
</li>
<li>
<a href="http://docs.pylonshq.com/pyramid/dev/#support-and-development">Support and Development</a>
</li>
<li>
<a href="irc://irc.freenode.net#pyramid">IRC Channel</a>
</li>
</ul>
</div>
</div>
</div>
</div>
<div id="footer">
<div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div>
</div>
</body>
</html>
+103
View File
@@ -0,0 +1,103 @@
import unittest
from pyramid.config import Configurator
from pyramid import testing
import os
from webtest import TestApp
from pyramidapp import main
from paste.deploy import loadapp
dirname = os.path.abspath(__file__)
dirname = os.path.dirname(dirname)
dirname = os.path.dirname(dirname)
def _initTestingDB():
from sqlalchemy import create_engine
from pyramidapp.models import initialize_sql
session = initialize_sql(create_engine('sqlite://'))
return session
class TestController(unittest.TestCase):
def setUp(self):
app = loadapp('config:%s' % os.path.join(dirname, 'development.ini'))
self.app = TestApp(app)
self.config = Configurator(autocommit=True)
self.config.begin()
#_initTestingDB()
def tearDown(self):
self.config.end()
def test_index(self):
# index
resp = self.app.get('/admin/')
resp.mustcontain('/admin/Foo')
resp = resp.click('Foo')
## Simple model
# add page
resp.mustcontain('/admin/Foo/new')
resp = resp.click('New Foo')
resp.mustcontain('/admin/Foo"')
form = resp.forms[0]
form['Foo--bar'] = 'value'
resp = form.submit()
assert resp.headers['location'] == 'http://localhost/admin/Foo', resp
# model index
resp = resp.follow()
resp.mustcontain('<td>value</td>')
# edit page
form = resp.forms[0]
resp = form.submit()
form = resp.forms[0]
form['Foo-1-bar'] = 'new value'
#form['_method'] = 'PUT'
resp = form.submit()
resp = resp.follow()
# model index
resp.mustcontain('<td>new value</td>')
# delete
resp = self.app.get('/admin/Foo')
resp.mustcontain('<td>new value</td>')
resp = resp.forms[1].submit()
resp = resp.follow()
assert 'new value' not in resp, resp
def test_json(self):
# index
response = self.app.get('/admin/json')
response.mustcontain('{"models": {', '"Foo": "http://localhost/admin/Foo/json"')
## Simple model
# add page
response = self.app.post('/admin/Foo/json',
{'Foo--bar': 'value'})
data = response.json
id = data['item_url'].split('/')[-1]
response.mustcontain('"Foo-%s-bar": "value"' % id)
# get data
response = self.app.get(str(data['item_url']))
response.mustcontain('"Foo-%s-bar": "value"' % id)
# edit page
response = self.app.post(str(data['item_url']), {'Foo-%s-bar' % id: 'new value'})
response.mustcontain('"Foo-%s-bar": "new value"' % id)
# delete
response = self.app.delete(str(data['item_url']))
+7
View File
@@ -0,0 +1,7 @@
from pyramidapp.models import DBSession
from pyramidapp.models import MyModel
def my_view(request):
dbsession = DBSession()
root = dbsession.query(MyModel).filter(MyModel.name==u'root').first()
return {'root':root, 'project':'pyramidapp'}
+27
View File
@@ -0,0 +1,27 @@
[nosetests]
match=^test
nocapture=1
cover-package=pyramidapp
with-coverage=1
cover-erase=1
[compile_catalog]
directory = pyramidapp/locale
domain = pyramidapp
statistics = true
[extract_messages]
add_comments = TRANSLATORS:
output_file = pyramidapp/locale/pyramidapp.pot
width = 80
[init_catalog]
domain = pyramidapp
input_file = pyramidapp/locale/pyramidapp.pot
output_dir = pyramidapp/locale
[update_catalog]
domain = pyramidapp
input_file = pyramidapp/locale/pyramidapp.pot
output_dir = pyramidapp/locale
previous = true
+47
View File
@@ -0,0 +1,47 @@
import os
import sys
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
README = open(os.path.join(here, 'README.txt')).read()
CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
requires = [
'pyramid',
'SQLAlchemy',
'transaction',
'repoze.tm2',
'zope.sqlalchemy',
'WebError',
]
if sys.version_info[:3] < (2,5,0):
requires.append('pysqlite')
setup(name='pyramidapp',
version='0.0',
description='pyramidapp',
long_description=README + '\n\n' + CHANGES,
classifiers=[
"Programming Language :: Python",
"Framework :: Pylons",
"Topic :: Internet :: WWW/HTTP",
"Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
],
author='',
author_email='',
url='',
keywords='web wsgi bfg pylons pyramid',
packages=find_packages(),
include_package_data=True,
zip_safe=False,
test_suite='pyramidapp',
install_requires = requires,
entry_points = """\
[paste.app_factory]
main = pyramidapp:main
""",
paster_plugins=['pyramid'],
)
+27
View File
@@ -0,0 +1,27 @@
[nosetests]
match = ^test
nocapture = 1
cover-package = pyramidapp
with-coverage = 1
cover-erase = 1
[compile_catalog]
directory = pyramid_formalchemy/locale
domain = pyramid_formalchemy
statistics = true
[extract_messages]
add_comments = TRANSLATORS:
output_file = pyramid_formalchemy/locale/pyramid_formalchemy.pot
width = 80
[init_catalog]
domain = pyramid_formalchemy
input_file = pyramid_formalchemy/locale/pyramid_formalchemy.pot
output_dir = pyramid_formalchemy/locale
[update_catalog]
domain = pyramid_formalchemy
input_file = pyramid_formalchemy/locale/pyramid_formalchemy.pot
output_dir = pyramid_formalchemy/locale
previous = true
+30
View File
@@ -0,0 +1,30 @@
import os
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
README = open(os.path.join(here, 'README.txt')).read()
CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
requires = ['pyramid', 'WebError', 'FormAlchemy']
setup(name='pyramid_formalchemy',
version='0.0',
description='pyramid_formalchemy',
long_description=README + '\n\n' + CHANGES,
classifiers=[
"Programming Language :: Python",
"Framework :: Pylons",
"Topic :: Internet :: WWW/HTTP",
"Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
],
author='Gael Pasgrimaud',
author_email='gael@gawel.org',
url='',
keywords='web pyramid pylons formalchemy',
packages=find_packages(exclude=['pyramidapp']),
include_package_data=True,
zip_safe=False,
install_requires=requires,
)