Created the pecan project for containers for API
Co-Authored-By: Digambar Patil <digambarpat@gmail.com> Co-Authored-By: Steven Dake <sdake@redhat.com> Change-Id: I886a26ded99708f39bba22d0ebd08ce99cd26020
This commit is contained in:
parent
84d943ec2d
commit
3d15bd1ba8
1
containers/MANIFEST.in
Normal file
1
containers/MANIFEST.in
Normal file
@ -0,0 +1 @@
|
||||
recursive-include public *
|
0
containers/api/__init__.py
Normal file
0
containers/api/__init__.py
Normal file
14
containers/api/app.py
Normal file
14
containers/api/app.py
Normal file
@ -0,0 +1,14 @@
|
||||
from pecan import make_app
|
||||
from api import model
|
||||
|
||||
|
||||
def setup_app(config):
|
||||
|
||||
model.init_model()
|
||||
app_conf = dict(config.app)
|
||||
|
||||
return make_app(
|
||||
app_conf.pop('root'),
|
||||
logging=getattr(config, 'logging', {}),
|
||||
**app_conf
|
||||
)
|
0
containers/api/controllers/__init__.py
Normal file
0
containers/api/controllers/__init__.py
Normal file
22
containers/api/controllers/root.py
Normal file
22
containers/api/controllers/root.py
Normal file
@ -0,0 +1,22 @@
|
||||
from pecan import expose, redirect
|
||||
from webob.exc import status_map
|
||||
|
||||
|
||||
class RootController(object):
|
||||
|
||||
@expose(generic=True, template='index.html')
|
||||
def index(self):
|
||||
return dict()
|
||||
|
||||
@index.when(method='POST')
|
||||
def index_post(self, q):
|
||||
redirect('http://pecan.readthedocs.org/en/latest/search.html?q=%s' % q)
|
||||
|
||||
@expose('error.html')
|
||||
def error(self, status):
|
||||
try:
|
||||
status = int(status)
|
||||
except ValueError: # pragma: no cover
|
||||
status = 500
|
||||
message = getattr(status_map.get(status), 'explanation', '')
|
||||
return dict(status=status, message=message)
|
15
containers/api/model/__init__.py
Normal file
15
containers/api/model/__init__.py
Normal file
@ -0,0 +1,15 @@
|
||||
from pecan import conf # noqa
|
||||
|
||||
|
||||
def init_model():
|
||||
"""
|
||||
This is a stub method which is called at application startup time.
|
||||
|
||||
If you need to bind to a parsed database configuration, set up tables or
|
||||
ORM classes, or perform any database initialization, this is the
|
||||
recommended place to do it.
|
||||
|
||||
For more information working with databases, and some common recipes,
|
||||
see http://pecan.readthedocs.org/en/latest/databases.html
|
||||
"""
|
||||
pass
|
12
containers/api/templates/error.html
Normal file
12
containers/api/templates/error.html
Normal file
@ -0,0 +1,12 @@
|
||||
<%inherit file="layout.html" />
|
||||
|
||||
## provide definitions for blocks we want to redefine
|
||||
<%def name="title()">
|
||||
Server Error ${status}
|
||||
</%def>
|
||||
|
||||
## now define the body of the template
|
||||
<header>
|
||||
<h1>Server Error ${status}</h1>
|
||||
</header>
|
||||
<p>${message}</p>
|
34
containers/api/templates/index.html
Normal file
34
containers/api/templates/index.html
Normal file
@ -0,0 +1,34 @@
|
||||
<%inherit file="layout.html" />
|
||||
|
||||
## provide definitions for blocks we want to redefine
|
||||
<%def name="title()">
|
||||
Welcome to Pecan!
|
||||
</%def>
|
||||
|
||||
## now define the body of the template
|
||||
<header>
|
||||
<h1><img src="/images/logo.png" /></h1>
|
||||
</header>
|
||||
|
||||
<div id="content">
|
||||
|
||||
<p>This is a sample Pecan project.</p>
|
||||
|
||||
<p>
|
||||
Instructions for getting started can be found online at <a
|
||||
href="http://pecanpy.org" target="window">pecanpy.org</a>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
...or you can search the documentation here:
|
||||
</p>
|
||||
|
||||
<form method="POST" action="/">
|
||||
<fieldset>
|
||||
<input name="q" />
|
||||
<input type="submit" value="Search" />
|
||||
</fieldset>
|
||||
<small>Enter search terms or a module, class or function name.</small>
|
||||
</form>
|
||||
|
||||
</div>
|
22
containers/api/templates/layout.html
Normal file
22
containers/api/templates/layout.html
Normal file
@ -0,0 +1,22 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>${self.title()}</title>
|
||||
${self.style()}
|
||||
${self.javascript()}
|
||||
</head>
|
||||
<body>
|
||||
${self.body()}
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<%def name="title()">
|
||||
Default Title
|
||||
</%def>
|
||||
|
||||
<%def name="style()">
|
||||
<link rel="stylesheet" type="text/css" media="screen" href="/css/style.css" />
|
||||
</%def>
|
||||
|
||||
<%def name="javascript()">
|
||||
<script language="text/javascript" src="/javascript/shared.js"></script>
|
||||
</%def>
|
22
containers/api/tests/__init__.py
Normal file
22
containers/api/tests/__init__.py
Normal file
@ -0,0 +1,22 @@
|
||||
import os
|
||||
from unittest import TestCase
|
||||
from pecan import set_config
|
||||
from pecan.testing import load_test_app
|
||||
|
||||
__all__ = ['FunctionalTest']
|
||||
|
||||
|
||||
class FunctionalTest(TestCase):
|
||||
"""
|
||||
Used for functional tests where you need to test your
|
||||
literal application and its integration with the framework.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.app = load_test_app(os.path.join(
|
||||
os.path.dirname(__file__),
|
||||
'config.py'
|
||||
))
|
||||
|
||||
def tearDown(self):
|
||||
set_config({}, overwrite=True)
|
25
containers/api/tests/config.py
Normal file
25
containers/api/tests/config.py
Normal file
@ -0,0 +1,25 @@
|
||||
# Server Specific Configurations
|
||||
server = {
|
||||
'port': '8080',
|
||||
'host': '0.0.0.0'
|
||||
}
|
||||
|
||||
# Pecan Application Configurations
|
||||
app = {
|
||||
'root': 'api.controllers.root.RootController',
|
||||
'modules': ['api'],
|
||||
'static_root': '%(confdir)s/../../public',
|
||||
'template_path': '%(confdir)s/../templates',
|
||||
'debug': True,
|
||||
'errors': {
|
||||
'404': '/error/404',
|
||||
'__force_dict__': True
|
||||
}
|
||||
}
|
||||
|
||||
# Custom Configurations must be in Python dictionary format::
|
||||
#
|
||||
# foo = {'bar':'baz'}
|
||||
#
|
||||
# All configurations are accessible at::
|
||||
# pecan.conf
|
22
containers/api/tests/test_functional.py
Normal file
22
containers/api/tests/test_functional.py
Normal file
@ -0,0 +1,22 @@
|
||||
from unittest import TestCase
|
||||
from webtest import TestApp
|
||||
from api.tests import FunctionalTest
|
||||
|
||||
|
||||
class TestRootController(FunctionalTest):
|
||||
|
||||
def test_get(self):
|
||||
response = self.app.get('/')
|
||||
assert response.status_int == 200
|
||||
|
||||
def test_search(self):
|
||||
response = self.app.post('/', params={'q': 'RestController'})
|
||||
assert response.status_int == 302
|
||||
assert response.headers['Location'] == (
|
||||
'http://pecan.readthedocs.org/en/latest/search.html'
|
||||
'?q=RestController'
|
||||
)
|
||||
|
||||
def test_get_not_found(self):
|
||||
response = self.app.get('/a/bogus/url', expect_errors=True)
|
||||
assert response.status_int == 404
|
7
containers/api/tests/test_units.py
Normal file
7
containers/api/tests/test_units.py
Normal file
@ -0,0 +1,7 @@
|
||||
from unittest import TestCase
|
||||
|
||||
|
||||
class TestUnits(TestCase):
|
||||
|
||||
def test_units(self):
|
||||
assert 5 * 5 == 25
|
54
containers/config.py
Normal file
54
containers/config.py
Normal file
@ -0,0 +1,54 @@
|
||||
# Server Specific Configurations
|
||||
server = {
|
||||
'port': '8080',
|
||||
'host': '0.0.0.0'
|
||||
}
|
||||
|
||||
# Pecan Application Configurations
|
||||
app = {
|
||||
'root': 'api.controllers.root.RootController',
|
||||
'modules': ['api'],
|
||||
'static_root': '%(confdir)s/public',
|
||||
'template_path': '%(confdir)s/api/templates',
|
||||
'debug': True,
|
||||
'errors': {
|
||||
404: '/error/404',
|
||||
'__force_dict__': True
|
||||
}
|
||||
}
|
||||
|
||||
logging = {
|
||||
'root': {'level': 'INFO', 'handlers': ['console']},
|
||||
'loggers': {
|
||||
'api': {'level': 'DEBUG', 'handlers': ['console']},
|
||||
'pecan.commands.serve': {'level': 'DEBUG', 'handlers': ['console']},
|
||||
'py.warnings': {'handlers': ['console']},
|
||||
'__force_dict__': True
|
||||
},
|
||||
'handlers': {
|
||||
'console': {
|
||||
'level': 'DEBUG',
|
||||
'class': 'logging.StreamHandler',
|
||||
'formatter': 'color'
|
||||
}
|
||||
},
|
||||
'formatters': {
|
||||
'simple': {
|
||||
'format': ('%(asctime)s %(levelname)-5.5s [%(name)s]'
|
||||
'[%(threadName)s] %(message)s')
|
||||
},
|
||||
'color': {
|
||||
'()': 'pecan.log.ColorFormatter',
|
||||
'format': ('%(asctime)s [%(padded_color_levelname)s] [%(name)s]'
|
||||
'[%(threadName)s] %(message)s'),
|
||||
'__force_dict__': True
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Custom Configurations must be in Python dictionary format::
|
||||
#
|
||||
# foo = {'bar':'baz'}
|
||||
#
|
||||
# All configurations are accessible at::
|
||||
# pecan.conf
|
43
containers/public/css/style.css
Normal file
43
containers/public/css/style.css
Normal file
@ -0,0 +1,43 @@
|
||||
body {
|
||||
background: #311F00;
|
||||
color: white;
|
||||
font-family: 'Helvetica Neue', 'Helvetica', 'Verdana', sans-serif;
|
||||
padding: 1em 2em;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #FAFF78;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
div#content {
|
||||
width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
form {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
input.error {
|
||||
background: #FAFF78;
|
||||
}
|
||||
|
||||
header {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: 'Futura-CondensedExtraBold', 'Futura', 'Helvetica', sans-serif;
|
||||
text-transform: uppercase;
|
||||
}
|
BIN
containers/public/images/logo.png
Normal file
BIN
containers/public/images/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
6
containers/setup.cfg
Normal file
6
containers/setup.cfg
Normal file
@ -0,0 +1,6 @@
|
||||
[nosetests]
|
||||
match=^test
|
||||
where=api
|
||||
nocapture=1
|
||||
cover-package=api
|
||||
cover-erase=1
|
22
containers/setup.py
Normal file
22
containers/setup.py
Normal file
@ -0,0 +1,22 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
try:
|
||||
from setuptools import setup, find_packages
|
||||
except ImportError:
|
||||
from ez_setup import use_setuptools
|
||||
use_setuptools()
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
setup(
|
||||
name='api',
|
||||
version='0.1',
|
||||
description='',
|
||||
author='',
|
||||
author_email='',
|
||||
install_requires=[
|
||||
"pecan",
|
||||
],
|
||||
test_suite='api',
|
||||
zip_safe=False,
|
||||
include_package_data=True,
|
||||
packages=find_packages(exclude=['ez_setup'])
|
||||
)
|
Loading…
Reference in New Issue
Block a user