Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
C
corepost
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
nexlab
corepost
Commits
021581bb
Commit
021581bb
authored
Aug 30, 2011
by
Jacek Furmankiewicz
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
multi resource support + BDD tests + docs
parent
a08b5e25
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
166 additions
and
36 deletions
+166
-36
README.md
README.md
+80
-4
url_routing.feature
corepost/test/feature/url_routing.feature
+17
-0
multi_resource.py
corepost/test/multi_resource.py
+46
-0
steps.py
corepost/test/steps.py
+14
-14
submodule_test.py
corepost/test/submodule_test.py
+0
-13
web.py
corepost/web.py
+8
-3
setup.py
setup.py
+1
-2
No files found.
README.md
View file @
021581bb
...
...
@@ -4,11 +4,13 @@ Twisted REST micro-framework
Based on
*Flask*
API, with integrated multiprocessing support for full usage of all CPUs.
Provides a more Flask/Sinatra-style API on top of the core
*twisted.web*
APIs.
Geared towards creating REST-oriented server platforms
(e.g. as a source of data for a Javascript MVC app)
.
Tested
exclusively on PyPy
for maximum performance.
Geared towards creating REST-oriented server platforms.
Tested
on PyPy (recommended) and Python 2.7
for maximum performance.
Example
-------
Single REST module example
--------------------------
The simplest possible REST application:
from corepost.web import CorePost
from corepost.enums import Http
...
...
@@ -28,7 +30,73 @@ Example
return "%s - %s" % (numericid,stringid)
if __name__ == '__main__':
# shortcut method to run a CorePost Resource as a single site
app.run()
Multiple module REST application
--------------------------------
The key CorePost object is just an extension of the regular twisted.web Resource object
and as such can easily be used to assemble a multi-module REST applications with
different CorePost objects serving from different context paths:
from corepost.web import CorePost
from corepost.enums import Http
from twisted.web.resource import Resource
from twisted.internet import reactor
from twisted.web.server import Site
# Home module
home = CorePost()
@home.route("/")
def home_root(request,**kwargs):
return "HOME %s" % kwargs
# First module
module1 = CorePost('module1')
@module1.route("/",Http.GET)
def module1_get(request,**kwargs):
return request.path
@module1.route("/sub",Http.GET)
def module1e_sub(request,**kwargs):
return request.path
# Second module
module2 = CorePost('module2')
@module2.route("/",Http.GET)
def module2_get(request,**kwargs):
return request.path
@module2.route("/sub",Http.GET)
def module2_sub(request,**kwargs):
return request.path
if __name__ == '__main__':
app = Resource()
app.putChild(home.path, home)
app.putChild(module1.path,module1)
app.putChild(module2.path,module2)
factory = Site(app)
reactor.listenTCP(8080, factory)
reactor.run()
The example above creates 3 modules ("/","module1","/module2") and exposes the following URLs:
http://127.0.0.1:8080
http://127.0.0.1:8080/
http://127.0.0.1:8080/module1
http://127.0.0.1:8080/module1/
http://127.0.0.1:8080/module1/sub
http://127.0.0.1:8080/module2
http://127.0.0.1:8080/module2/
http://127.0.0.1:8080/module2/sub
@defer.inlineCallbacks support
------------------------------
...
...
@@ -47,6 +115,14 @@ Performance
On par with raw
*twisted.web*
performance. Minimal overhead for URL routing and function argument extraction.
BDD unit tests
--------------
All unit tests for CorePost are in BDD feature format, using Freshen.
Can be run using:
nosetests --with-freshen -v
Plans
-----
...
...
corepost/test/feature/url_routing.feature
View file @
021581bb
...
...
@@ -51,4 +51,21 @@ Feature: URL routing
When as user 'None
:
None' I PUT 'http
:
//127.0.0.1
:
8080/postput'
with
'test=value&test2=value2'
Then
I expect HTTP code 200
And I expect content contains '{'test'
:
'value', 'test2'
:
'value2'}'
@multi
Scenario Outline
:
Multiple resources with submodules
Given 'multi_resource' is running
When as user 'None
:
None'
I
GET '<url>'
Then
I expect HTTP code 200
Examples
:
|
url
|
|
http://127.0.0.1:8081
|
|
http://127.0.0.1:8081/
|
|
http://127.0.0.1:8081/module1
|
|
http://127.0.0.1:8081/module1/
|
|
http://127.0.0.1:8081/module1/sub
|
|
http://127.0.0.1:8081/module2
|
|
http://127.0.0.1:8081/module2/
|
|
http://127.0.0.1:8081/module2/sub
|
\ No newline at end of file
corepost/test/multi_resource.py
0 → 100644
View file @
021581bb
'''
A CorePost module1 that can be merged into the main CorePost Resource
'''
from
corepost.web
import
CorePost
from
corepost.enums
import
Http
from
twisted.web.resource
import
Resource
from
twisted.internet
import
reactor
from
twisted.web.server
import
Site
home
=
CorePost
()
@
home
.
route
(
"/"
)
def
home_root
(
request
,
**
kwargs
):
return
"HOME
%
s"
%
kwargs
module1
=
CorePost
(
'module1'
)
@
module1
.
route
(
"/"
,
Http
.
GET
)
def
module1_get
(
request
,
**
kwargs
):
return
request
.
path
@
module1
.
route
(
"/sub"
,
Http
.
GET
)
def
module1e_sub
(
request
,
**
kwargs
):
return
request
.
path
module2
=
CorePost
(
'module2'
)
@
module2
.
route
(
"/"
,
Http
.
GET
)
def
module2_get
(
request
,
**
kwargs
):
return
request
.
path
@
module2
.
route
(
"/sub"
,
Http
.
GET
)
def
module2_sub
(
request
,
**
kwargs
):
return
request
.
path
def
run_app_multi
():
app
=
Resource
()
app
.
putChild
(
home
.
path
,
home
)
app
.
putChild
(
module1
.
path
,
module1
)
app
.
putChild
(
module2
.
path
,
module2
)
factory
=
Site
(
app
)
reactor
.
listenTCP
(
8081
,
factory
)
#@UndefinedVariable
reactor
.
run
()
#@UndefinedVariable
corepost/test/steps.py
View file @
021581bb
...
...
@@ -5,11 +5,12 @@ Common Freshen BDD steps
'''
from
multiprocessing
import
Process
import
httplib2
,
json
,
re
,
time
from
freshen
import
Before
,
After
,
Given
,
When
,
Then
,
scc
,
assert_equals
,
assert_true
#@UnresolvedImport
from
freshen
import
Before
,
After
,
Given
,
When
,
Then
,
scc
,
glc
,
assert_equals
,
assert_true
#@UnresolvedImport
from
urllib
import
urlencode
from
corepost.test.home_resource
import
run_app_home
from
corepost.test.multi_resource
import
run_app_multi
apps
=
{
'home_resource'
:
run_app_home
}
apps
=
{
'home_resource'
:
run_app_home
,
'multi_resource'
:
run_app_multi
}
def
as_dict
(
parameters
):
dict_val
=
{}
...
...
@@ -25,26 +26,25 @@ def as_dict(parameters):
@
Before
def
setup
(
slc
):
scc
.
processes
=
[]
scc
.
http_headers
=
{}
@
After
def
cleanup
(
slc
):
# shut down processes
for
process
in
scc
.
processes
:
process
.
terminate
()
##################################
# GIVEN
##################################
@
Given
(
r"^'(.+)' is running\s*$"
)
def
given_process_is_running
(
processname
):
process
=
Process
(
target
=
apps
[
processname
])
process
.
daemon
=
True
process
.
start
()
scc
.
processes
.
append
(
process
)
time
.
sleep
(
0.25
)
# let it start up
if
glc
.
processes
==
None
:
glc
.
processes
=
{}
if
processname
not
in
glc
.
processes
:
# start a process only once, keep it running
# to make test runs faster
process
=
Process
(
target
=
apps
[
processname
])
process
.
daemon
=
True
process
.
start
()
time
.
sleep
(
0.25
)
# let it start up
glc
.
processes
[
processname
]
=
process
##################################
# WHEN
...
...
corepost/test/submodule_test.py
deleted
100644 → 0
View file @
a08b5e25
'''
A CorePost submodule that can be merged into the main CorePost Resource
'''
from
corepost.web
import
CorePost
from
corepost.enums
import
Http
submodule
=
CorePost
()
submodule
.
isLeaf
=
True
@
submodule
.
route
(
"/test"
,
Http
.
GET
)
def
submodule_get
(
request
,
**
kwargs
):
return
request
.
path
\ No newline at end of file
corepost/web.py
View file @
021581bb
...
...
@@ -96,7 +96,7 @@ class CorePost(Resource):
'''
isLeaf
=
True
def
__init__
(
self
):
def
__init__
(
self
,
path
=
''
):
'''
Constructor
'''
...
...
@@ -104,6 +104,11 @@ class CorePost(Resource):
self
.
__urls
=
defaultdict
(
dict
)
self
.
__cachedUrls
=
defaultdict
(
dict
)
self
.
__methods
=
{}
self
.
__path
=
path
@
property
def
path
(
self
):
return
self
.
__path
def
__registerFunction
(
self
,
f
,
url
,
methods
,
accepts
,
produces
,
cache
):
if
f
not
in
self
.
__methods
.
values
():
...
...
@@ -116,7 +121,7 @@ class CorePost(Resource):
self
.
__methods
[
url
]
=
f
def
route
(
self
,
url
,
methods
=
[]
,
accepts
=
MediaType
.
WILDCARD
,
produces
=
None
,
cache
=
True
):
def
route
(
self
,
url
,
methods
=
(
Http
.
GET
,)
,
accepts
=
MediaType
.
WILDCARD
,
produces
=
None
,
cache
=
True
):
"""Main decorator for registering REST functions """
def
wrap
(
f
):
self
.
__registerFunction
(
f
,
url
,
methods
,
accepts
,
produces
,
cache
)
...
...
@@ -143,7 +148,7 @@ class CorePost(Resource):
"""Finds the appropriate router and dispatches the request to the registered function"""
# see if already cached
path
=
'/'
+
'/'
.
join
(
request
.
postpath
)
urlrouter
,
pathargs
=
None
,
None
if
path
in
self
.
__cachedUrls
[
request
.
method
]:
cachedUrl
=
self
.
__cachedUrls
[
request
.
method
][
path
]
...
...
setup.py
View file @
021581bb
...
...
@@ -16,7 +16,7 @@ def read(fname):
setup
(
name
=
"CorePost"
,
version
=
"0.0.
2
"
,
version
=
"0.0.
3
"
,
author
=
"Jacek Furmankiewicz"
,
author_email
=
"jacek99@gmail.com"
,
description
=
(
"A Twisted Web REST micro-framework"
),
...
...
@@ -37,7 +37,6 @@ setup(
],
install_requires
=
[
'twisted>=11.0.0'
,
'twisted.internet.processes>=1.0b1'
,
'httplib2>=0.7.1'
,
'freshen>=0.2'
,
],
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment