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
446c73bf
Commit
446c73bf
authored
Sep 05, 2011
by
Jacek Furmankiewicz
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
0.0.6: reworked API to be class/method oriented and avoid global objects
parent
fa5d53b9
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
131 additions
and
125 deletions
+131
-125
arguments.py
corepost/test/arguments.py
+18
-17
home_resource.py
corepost/test/home_resource.py
+38
-34
misc.py
corepost/test/misc.py
+0
-24
multi_resource.py
corepost/test/multi_resource.py
+25
-25
web.py
corepost/web.py
+48
-24
setup.py
setup.py
+2
-1
No files found.
corepost/test/arguments.py
View file @
446c73bf
...
@@ -3,30 +3,31 @@ Argument extraction tests
...
@@ -3,30 +3,31 @@ Argument extraction tests
@author: jacekf
@author: jacekf
'''
'''
from
corepost.web
import
CorePost
,
validate
from
corepost.web
import
CorePost
,
validate
,
route
from
corepost.enums
import
Http
from
corepost.enums
import
Http
from
formencode
import
Schema
,
validators
from
formencode
import
Schema
,
validators
app
=
CorePost
()
class
TestSchema
(
Schema
):
class
TestSchema
(
Schema
):
allow_extra_fields
=
True
allow_extra_fields
=
True
childId
=
validators
.
Regex
(
regex
=
"^jacekf|test$"
)
childId
=
validators
.
Regex
(
regex
=
"^jacekf|test$"
)
@
app
.
route
(
"/int/<int:intarg>/float/<float:floatarg>/string/<stringarg>"
,
Http
.
GET
)
class
ArgumentApp
(
CorePost
):
def
test
(
request
,
intarg
,
floatarg
,
stringarg
,
**
kwargs
):
args
=
(
intarg
,
floatarg
,
stringarg
)
@
route
(
"/int/<int:intarg>/float/<float:floatarg>/string/<stringarg>"
,
Http
.
GET
)
return
"
%
s"
%
map
(
lambda
x
:
(
type
(
x
),
x
),
args
)
def
test
(
self
,
request
,
intarg
,
floatarg
,
stringarg
,
**
kwargs
):
args
=
(
intarg
,
floatarg
,
stringarg
)
@
app
.
route
(
"/validate/<int:rootId>/schema"
,
Http
.
POST
)
return
"
%
s"
%
map
(
lambda
x
:
(
type
(
x
),
x
),
args
)
@
validate
(
schema
=
TestSchema
)
def
postValidateSchema
(
request
,
rootId
,
childId
,
**
kwargs
):
@
route
(
"/validate/<int:rootId>/schema"
,
Http
.
POST
)
return
"
%
s -
%
s -
%
s"
%
(
rootId
,
childId
,
kwargs
)
@
validate
(
schema
=
TestSchema
())
def
postValidateSchema
(
self
,
request
,
rootId
,
childId
,
**
kwargs
):
@
app
.
route
(
"/validate/<int:rootId>/custom"
,
Http
.
POST
)
return
"
%
s -
%
s -
%
s"
%
(
rootId
,
childId
,
kwargs
)
@
validate
(
childId
=
validators
.
Regex
(
regex
=
"^jacekf|test$"
))
def
postValidateCustom
(
request
,
rootId
,
childId
,
**
kwargs
):
@
route
(
"/validate/<int:rootId>/custom"
,
Http
.
POST
)
return
"
%
s -
%
s -
%
s"
%
(
rootId
,
childId
,
kwargs
)
@
validate
(
childId
=
validators
.
Regex
(
regex
=
"^jacekf|test$"
))
def
postValidateCustom
(
self
,
request
,
rootId
,
childId
,
**
kwargs
):
return
"
%
s -
%
s -
%
s"
%
(
rootId
,
childId
,
kwargs
)
def
run_app_arguments
():
def
run_app_arguments
():
app
=
ArgumentApp
()
app
.
run
(
8082
)
app
.
run
(
8082
)
\ No newline at end of file
corepost/test/home_resource.py
View file @
446c73bf
...
@@ -3,42 +3,46 @@ Server tests
...
@@ -3,42 +3,46 @@ Server tests
@author: jacekf
@author: jacekf
'''
'''
from
corepost.web
import
CorePost
from
corepost.web
import
CorePost
,
route
from
corepost.enums
import
Http
from
corepost.enums
import
Http
from
twisted.internet
import
defer
from
twisted.internet
import
defer
app
=
CorePost
()
class
HomeApp
(
CorePost
):
@
app
.
route
(
"/"
,
Http
.
GET
)
@
route
(
"/"
,
Http
.
GET
)
@
defer
.
inlineCallbacks
@
defer
.
inlineCallbacks
def
root
(
request
,
**
kwargs
):
def
root
(
self
,
request
,
**
kwargs
):
yield
1
yield
1
request
.
write
(
"
%
s"
%
kwargs
)
request
.
write
(
"
%
s"
%
kwargs
)
request
.
finish
()
request
.
finish
()
@
app
.
route
(
"/test"
,
Http
.
GET
)
@
route
(
"/test"
,
Http
.
GET
)
def
test
(
request
,
**
kwargs
):
def
test
(
self
,
request
,
**
kwargs
):
return
"
%
s"
%
kwargs
return
"
%
s"
%
kwargs
@
app
.
route
(
"/test/<int:numericid>/resource/<stringid>"
,
Http
.
GET
)
@
route
(
"/test/<int:numericid>/resource/<stringid>"
,
Http
.
GET
)
def
test_get_resources
(
request
,
numericid
,
stringid
,
**
kwargs
):
def
test_get_resources
(
self
,
request
,
numericid
,
stringid
,
**
kwargs
):
return
"
%
s -
%
s"
%
(
numericid
,
stringid
)
return
"
%
s -
%
s"
%
(
numericid
,
stringid
)
@
app
.
route
(
"/post"
,(
Http
.
POST
,
Http
.
PUT
))
@
route
(
"/post"
,(
Http
.
POST
,
Http
.
PUT
))
def
test_post
(
request
,
**
kwargs
):
def
test_post
(
self
,
request
,
**
kwargs
):
return
"
%
s"
%
kwargs
return
"
%
s"
%
kwargs
@
app
.
route
(
"/put"
,(
Http
.
POST
,
Http
.
PUT
))
@
route
(
"/put"
,(
Http
.
POST
,
Http
.
PUT
))
def
test_put
(
request
,
**
kwargs
):
def
test_put
(
self
,
request
,
**
kwargs
):
return
"
%
s"
%
kwargs
return
"
%
s"
%
kwargs
@
app
.
route
(
"/postput"
,(
Http
.
POST
,
Http
.
PUT
))
@
route
(
"/postput"
,(
Http
.
POST
,
Http
.
PUT
))
def
test_postput
(
request
,
**
kwargs
):
def
test_postput
(
self
,
request
,
**
kwargs
):
return
"
%
s"
%
kwargs
return
"
%
s"
%
kwargs
@
app
.
route
(
"/delete"
,
Http
.
DELETE
)
@
route
(
"/delete"
,
Http
.
DELETE
)
def
test_delete
(
request
,
**
kwargs
):
def
test_delete
(
self
,
request
,
**
kwargs
):
return
"
%
s"
%
kwargs
return
"
%
s"
%
kwargs
def
run_app_home
():
def
run_app_home
():
app
.
run
()
app
=
HomeApp
()
\ No newline at end of file
app
.
run
()
if
__name__
==
"__main__"
:
run_app_home
()
\ No newline at end of file
corepost/test/misc.py
deleted
100644 → 0
View file @
fa5d53b9
'''
Created on 2011-09-02
Misc tests
@author: jacekf
'''
def
dec
(
f
):
print
"DEC"
def
wrap
():
print
"WRAP"
v
=
f
()
return
v
return
wrap
@
dec
def
test
():
print
"TEST3232"
if
__name__
==
"__main__"
:
test
()
test
()
test
()
\ No newline at end of file
corepost/test/multi_resource.py
View file @
446c73bf
...
@@ -2,43 +2,43 @@
...
@@ -2,43 +2,43 @@
A CorePost module1 that can be merged into the main CorePost Resource
A CorePost module1 that can be merged into the main CorePost Resource
'''
'''
from
corepost.web
import
CorePost
from
corepost.web
import
CorePost
,
route
from
corepost.enums
import
Http
from
corepost.enums
import
Http
from
twisted.web.resource
import
Resource
from
twisted.web.resource
import
Resource
from
twisted.internet
import
reactor
from
twisted.internet
import
reactor
from
twisted.web.server
import
Site
from
twisted.web.server
import
Site
home
=
CorePost
()
class
HomeApp
(
CorePost
):
@
home
.
route
(
"/"
)
@
route
(
"/"
)
def
home_root
(
request
,
**
kwargs
):
def
home_root
(
self
,
request
,
**
kwargs
):
return
"HOME
%
s"
%
kwargs
return
"HOME
%
s"
%
kwargs
module1
=
CorePost
(
'module1'
)
class
Module1
(
CorePost
):
@
module1
.
route
(
"/"
,
Http
.
GET
)
@
route
(
"/"
,
Http
.
GET
)
def
module1_get
(
request
,
**
kwargs
):
def
module1_get
(
self
,
request
,
**
kwargs
):
return
request
.
path
return
request
.
path
@
route
(
"/sub"
,
Http
.
GET
)
def
module1e_sub
(
self
,
request
,
**
kwargs
):
return
request
.
path
@
module1
.
route
(
"/sub"
,
Http
.
GET
)
class
Module2
(
CorePost
):
def
module1e_sub
(
request
,
**
kwargs
):
return
request
.
path
@
route
(
"/"
,
Http
.
GET
)
def
module2_get
(
self
,
request
,
**
kwargs
):
module2
=
CorePost
(
'module2'
)
return
request
.
path
@
module2
.
route
(
"/"
,
Http
.
GET
)
@
route
(
"/sub"
,
Http
.
GET
)
def
module2_get
(
request
,
**
kwargs
):
def
module2_sub
(
self
,
request
,
**
kwargs
):
return
request
.
path
return
request
.
path
@
module2
.
route
(
"/sub"
,
Http
.
GET
)
def
module2_sub
(
request
,
**
kwargs
):
return
request
.
path
def
run_app_multi
():
def
run_app_multi
():
app
=
Resource
()
app
=
Resource
()
app
.
putChild
(
home
.
path
,
home
)
app
.
putChild
(
''
,
HomeApp
()
)
app
.
putChild
(
module1
.
path
,
module1
)
app
.
putChild
(
'module1'
,
Module1
()
)
app
.
putChild
(
module2
.
path
,
module2
)
app
.
putChild
(
'module2'
,
Module2
()
)
factory
=
Site
(
app
)
factory
=
Site
(
app
)
reactor
.
listenTCP
(
8081
,
factory
)
#@UndefinedVariable
reactor
.
listenTCP
(
8081
,
factory
)
#@UndefinedVariable
...
...
corepost/web.py
View file @
446c73bf
...
@@ -3,16 +3,18 @@ Main server classes
...
@@ -3,16 +3,18 @@ Main server classes
@author: jacekf
@author: jacekf
'''
'''
import
re
,
copy
,
exceptions
from
twisted.internet
import
reactor
,
defer
from
twisted.web.resource
import
Resource
from
twisted.web.server
import
Site
,
NOT_DONE_YET
from
twisted.web.http
import
parse_qs
from
collections
import
defaultdict
from
collections
import
defaultdict
from
enums
import
MediaType
from
corepost.enums
import
Http
from
corepost.enums
import
Http
from
corepost.utils
import
getMandatoryArgumentNames
from
corepost.utils
import
getMandatoryArgumentNames
from
enums
import
MediaType
from
formencode
import
FancyValidator
,
Invalid
from
formencode
import
FancyValidator
,
Invalid
from
twisted.internet
import
reactor
,
defer
from
twisted.web.http
import
parse_qs
from
twisted.web.resource
import
Resource
from
twisted.web.server
import
Site
,
NOT_DONE_YET
import
re
import
copy
import
exceptions
class
RequestRouter
:
class
RequestRouter
:
''' Common class for containing info related to routing a request to a function '''
''' Common class for containing info related to routing a request to a function '''
...
@@ -21,17 +23,16 @@ class RequestRouter:
...
@@ -21,17 +23,16 @@ class RequestRouter:
__urlRegexReplace
=
{
""
:
r"(?P<arg>.+)"
,
"int"
:
r"(?P<arg>\d+)"
,
"float"
:
r"(?P<arg>\d+.?\d*)"
}
__urlRegexReplace
=
{
""
:
r"(?P<arg>.+)"
,
"int"
:
r"(?P<arg>\d+)"
,
"float"
:
r"(?P<arg>\d+.?\d*)"
}
__typeConverters
=
{
"int"
:
int
,
"float"
:
float
}
__typeConverters
=
{
"int"
:
int
,
"float"
:
float
}
def
__init__
(
self
,
f
,
url
,
method
,
accepts
,
produces
,
cache
):
def
__init__
(
self
,
f
,
url
,
method
s
,
accepts
,
produces
,
cache
):
self
.
__url
=
url
self
.
__url
=
url
self
.
__method
=
method
self
.
__method
s
=
methods
if
isinstance
(
methods
,
tuple
)
else
(
methods
,)
self
.
__accepts
=
accepts
self
.
__accepts
=
accepts
self
.
__produces
=
produces
self
.
__produces
=
produces
self
.
__cache
=
cache
self
.
__cache
=
cache
self
.
__f
=
f
self
.
__f
=
f
self
.
__argConverters
=
{}
# dict of arg names -> group index
self
.
__argConverters
=
{}
# dict of arg names -> group index
self
.
__schema
=
None
self
.
__validators
=
{}
self
.
__validators
=
{}
self
.
__mandatory
=
getMandatoryArgumentNames
(
f
)[
1
:]
self
.
__mandatory
=
getMandatoryArgumentNames
(
f
)[
2
:]
#parse URL into regex used for matching
#parse URL into regex used for matching
m
=
RequestRouter
.
__urlMatcher
.
findall
(
url
)
m
=
RequestRouter
.
__urlMatcher
.
findall
(
url
)
...
@@ -57,10 +58,13 @@ class RequestRouter:
...
@@ -57,10 +58,13 @@ class RequestRouter:
return
self
.
__cache
return
self
.
__cache
@
property
@
property
def
schema
(
self
):
def
methods
(
self
):
''''Returns the formencode Schema, if this URL uses custom validation schema'''
return
self
.
__methods
return
self
.
__schema
@
property
def
url
(
self
):
return
self
.
__url
def
addValidator
(
self
,
fieldName
,
validator
):
def
addValidator
(
self
,
fieldName
,
validator
):
'''Adds additional field-specific formencode validators'''
'''Adds additional field-specific formencode validators'''
self
.
__validators
[
fieldName
]
=
validator
self
.
__validators
[
fieldName
]
=
validator
...
@@ -83,12 +87,12 @@ class RequestRouter:
...
@@ -83,12 +87,12 @@ class RequestRouter:
else
:
else
:
return
None
return
None
def
call
(
self
,
request
,
**
kwargs
):
def
call
(
self
,
instance
,
request
,
**
kwargs
):
'''Forwards call to underlying method'''
'''Forwards call to underlying method'''
for
arg
in
self
.
__mandatory
:
for
arg
in
self
.
__mandatory
:
if
arg
not
in
kwargs
:
if
arg
not
in
kwargs
:
raise
TypeError
(
"Missing mandatory argument '
%
s'"
%
arg
)
raise
TypeError
(
"Missing mandatory argument '
%
s'"
%
arg
)
return
self
.
__f
(
request
,
**
kwargs
)
return
self
.
__f
(
instance
,
request
,
**
kwargs
)
class
CachedUrl
():
class
CachedUrl
():
'''
'''
...
@@ -113,7 +117,7 @@ class CorePost(Resource):
...
@@ -113,7 +117,7 @@ class CorePost(Resource):
'''
'''
isLeaf
=
True
isLeaf
=
True
def
__init__
(
self
,
path
=
''
,
schema
=
None
):
def
__init__
(
self
,
schema
=
None
):
'''
'''
Constructor
Constructor
'''
'''
...
@@ -122,13 +126,22 @@ class CorePost(Resource):
...
@@ -122,13 +126,22 @@ class CorePost(Resource):
self
.
__cachedUrls
=
defaultdict
(
dict
)
self
.
__cachedUrls
=
defaultdict
(
dict
)
self
.
__methods
=
{}
self
.
__methods
=
{}
self
.
__routers
=
{}
self
.
__routers
=
{}
self
.
__path
=
path
self
.
__schema
=
schema
self
.
__schema
=
schema
self
.
__registerRouters
()
@
property
@
property
def
path
(
self
):
def
path
(
self
):
return
self
.
__path
return
self
.
__path
def
__registerRouters
(
self
):
from
types
import
FunctionType
for
_
,
func
in
self
.
__class__
.
__dict__
.
iteritems
():
if
type
(
func
)
==
FunctionType
and
hasattr
(
func
,
'corepostRequestRouter'
):
rq
=
func
.
corepostRequestRouter
for
method
in
rq
.
methods
:
self
.
__urls
[
method
][
rq
.
url
]
=
rq
self
.
__routers
[
func
]
=
rq
# needed so that we can lookup the router for a specific function
def
__registerFunction
(
self
,
f
,
url
,
methods
,
accepts
,
produces
,
cache
):
def
__registerFunction
(
self
,
f
,
url
,
methods
,
accepts
,
produces
,
cache
):
if
f
not
in
self
.
__methods
.
values
():
if
f
not
in
self
.
__methods
.
values
():
if
not
isinstance
(
methods
,(
list
,
tuple
)):
if
not
isinstance
(
methods
,(
list
,
tuple
)):
...
@@ -142,11 +155,8 @@ class CorePost(Resource):
...
@@ -142,11 +155,8 @@ class CorePost(Resource):
self
.
__methods
[
url
]
=
f
self
.
__methods
[
url
]
=
f
def
route
(
self
,
url
,
methods
=
(
Http
.
GET
,),
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 """
'''Obsolete'''
def
wrap
(
f
,
*
args
,
**
kwargs
):
raise
RuntimeError
(
"Do not @app.route() any more, as of 0.0.6 API has been re-designed around class methods, see docs and examples"
)
self
.
__registerFunction
(
f
,
url
,
methods
,
accepts
,
produces
,
cache
)
return
f
return
wrap
def
render_GET
(
self
,
request
):
def
render_GET
(
self
,
request
):
""" Handles all GET requests """
""" Handles all GET requests """
...
@@ -202,7 +212,7 @@ class CorePost(Resource):
...
@@ -202,7 +212,7 @@ class CorePost(Resource):
#handle Deferreds natively
#handle Deferreds natively
try
:
try
:
val
=
urlrouter
.
call
(
request
,
**
allargs
)
val
=
urlrouter
.
call
(
self
,
request
,
**
allargs
)
if
isinstance
(
val
,
defer
.
Deferred
):
if
isinstance
(
val
,
defer
.
Deferred
):
# we assume the method will call request.finish()
# we assume the method will call request.finish()
...
@@ -243,6 +253,20 @@ class CorePost(Resource):
...
@@ -243,6 +253,20 @@ class CorePost(Resource):
# DECORATORS
# DECORATORS
#
#
##################################################################################################
##################################################################################################
def
route
(
url
,
methods
=
(
Http
.
GET
,),
accepts
=
MediaType
.
WILDCARD
,
produces
=
None
,
cache
=
True
):
'''
Main decorator for registering REST functions
'''
def
decorator
(
f
):
def
wrap
(
*
args
,
**
kwargs
):
return
f
router
=
RequestRouter
(
f
,
url
,
methods
,
accepts
,
produces
,
cache
)
setattr
(
wrap
,
'corepostRequestRouter'
,
router
)
return
wrap
return
decorator
def
validate
(
schema
=
None
,
**
vKwargs
):
def
validate
(
schema
=
None
,
**
vKwargs
):
'''
'''
...
...
setup.py
View file @
446c73bf
...
@@ -40,6 +40,7 @@ Links
...
@@ -40,6 +40,7 @@ Links
Changelog
Changelog
`````````
`````````
* 0.0.6 - redesigned API around classes and methods, rather than functions and global objects (after feedback from Twisted devs)
* 0.0.5 - added FormEncode validation for arguments
* 0.0.5 - added FormEncode validation for arguments
* 0.0.4 - path argument extraction, mandatory argument error checking
* 0.0.4 - path argument extraction, mandatory argument error checking
...
@@ -57,7 +58,7 @@ def read(fname):
...
@@ -57,7 +58,7 @@ def read(fname):
setup
(
setup
(
name
=
"CorePost"
,
name
=
"CorePost"
,
version
=
"0.0.
5
"
,
version
=
"0.0.
6
"
,
author
=
"Jacek Furmankiewicz"
,
author
=
"Jacek Furmankiewicz"
,
author_email
=
"jacek99@gmail.com"
,
author_email
=
"jacek99@gmail.com"
,
description
=
(
"A Twisted Web REST micro-framework"
),
description
=
(
"A Twisted Web REST micro-framework"
),
...
...
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