Browse Source

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
changes/87/133787/3
digambar Davanum Srinivas (dims) 5 years ago
parent
commit
3d15bd1ba8
18 changed files with 321 additions and 0 deletions
  1. +1
    -0
      containers/MANIFEST.in
  2. +0
    -0
      containers/api/__init__.py
  3. +14
    -0
      containers/api/app.py
  4. +0
    -0
      containers/api/controllers/__init__.py
  5. +22
    -0
      containers/api/controllers/root.py
  6. +15
    -0
      containers/api/model/__init__.py
  7. +12
    -0
      containers/api/templates/error.html
  8. +34
    -0
      containers/api/templates/index.html
  9. +22
    -0
      containers/api/templates/layout.html
  10. +22
    -0
      containers/api/tests/__init__.py
  11. +25
    -0
      containers/api/tests/config.py
  12. +22
    -0
      containers/api/tests/test_functional.py
  13. +7
    -0
      containers/api/tests/test_units.py
  14. +54
    -0
      containers/config.py
  15. +43
    -0
      containers/public/css/style.css
  16. BIN
      containers/public/images/logo.png
  17. +6
    -0
      containers/setup.cfg
  18. +22
    -0
      containers/setup.py

+ 1
- 0
containers/MANIFEST.in View File

@@ -0,0 +1 @@
recursive-include public *

+ 0
- 0
containers/api/__init__.py View File


+ 14
- 0
containers/api/app.py View 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
- 0
containers/api/controllers/__init__.py View File


+ 22
- 0
containers/api/controllers/root.py View 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
- 0
containers/api/model/__init__.py View 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
- 0
containers/api/templates/error.html View 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
- 0
containers/api/templates/index.html View 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
- 0
containers/api/templates/layout.html View 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
- 0
containers/api/tests/__init__.py View 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
- 0
containers/api/tests/config.py View 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
- 0
containers/api/tests/test_functional.py View 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
- 0
containers/api/tests/test_units.py View File

@@ -0,0 +1,7 @@
from unittest import TestCase


class TestUnits(TestCase):

def test_units(self):
assert 5 * 5 == 25

+ 54
- 0
containers/config.py View 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
- 0
containers/public/css/style.css View 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 View File

Before After
Width: 350  |  Height: 160  |  Size: 20KB

+ 6
- 0
containers/setup.cfg View File

@@ -0,0 +1,6 @@
[nosetests]
match=^test
where=api
nocapture=1
cover-package=api
cover-erase=1

+ 22
- 0
containers/setup.py View 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…
Cancel
Save