Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

arg_pattern kwarg for get_module_routes() including hyphen #80

Merged
merged 1 commit into from Sep 12, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 3 additions & 3 deletions demos/rest_api/cars/api/__init__.py
Expand Up @@ -102,15 +102,15 @@ def get(self, make, model, year):
# "<class 'cars.api.MakeListHandler'>"
# ],
# [
# "/api/cars/(?P<make>[a-zA-Z0-9_]+)/(?P<model>[a-zA-Z0-9_]+)/?$",
# "/api/cars/(?P<make>[a-zA-Z0-9_\-]+)/(?P<model>[a-zA-Z0-9_\-]+)/?$",
# "<class 'cars.api.ModelHandler'>"
# ],
# [
# "/api/cars/(?P<make>[a-zA-Z0-9_]+)/(?P<model>[a-zA-Z0-9_]+)/(?P<year>[a-zA-Z0-9_]+)/?$",
# "/api/cars/(?P<make>[a-zA-Z0-9_\-]+)/(?P<model>[a-zA-Z0-9_\-]+)/(?P<year>[a-zA-Z0-9_\-]+)/?$",
# "<class 'cars.api.YearHandler'>"
# ],
# [
# "/api/cars/(?P<make>[a-zA-Z0-9_]+)/?$",
# "/api/cars/(?P<make>[a-zA-Z0-9_\-]+)/?$",
# "<class 'cars.api.MakeHandler'>"
# ]
# ]
4 changes: 2 additions & 2 deletions tests/helloworld_API_documentation.md
Expand Up @@ -2,7 +2,7 @@

**Output schemas only represent `data` and not the full output; see output examples and the JSend specification.**

# /api/asynchelloworld/\(?P\<name\>\[a\-zA\-Z0\-9\_\]\+\)/?$
# /api/asynchelloworld/\(?P\<name\>\[a\-zA\-Z0\-9\_\\\-\]\+\)/?$

Content-Type: application/json

Expand Down Expand Up @@ -48,7 +48,7 @@ Shouts hello to the world (asynchronously)!
<br>
<br>

# /api/greeting/\(?P\<fname\>\[a\-zA\-Z0\-9\_\]\+\)/\(?P\<lname\>\[a\-zA\-Z0\-9\_\]\+\)/?$
# /api/greeting/\(?P\<fname\>\[a\-zA\-Z0\-9\_\\\-\]\+\)/\(?P\<lname\>\[a\-zA\-Z0\-9\_\\\-\]\+\)/?$

Content-Type: application/json

Expand Down
22 changes: 11 additions & 11 deletions tests/test_tornado_json.py
Expand Up @@ -48,21 +48,21 @@ def test_get_routes(self):
assert sorted(routes.get_routes(
helloworld)) == sorted([
("/api/helloworld/?", helloworld.api.HelloWorldHandler),
("/api/asynchelloworld/(?P<name>[a-zA-Z0-9_]+)/?$", helloworld.api.AsyncHelloWorld),
("/api/asynchelloworld/(?P<name>[a-zA-Z0-9_\\-]+)/?$", helloworld.api.AsyncHelloWorld),
("/api/postit/?", helloworld.api.PostIt),
("/api/greeting/(?P<fname>[a-zA-Z0-9_]+)/"
"(?P<lname>[a-zA-Z0-9_]+)/?$",
("/api/greeting/(?P<fname>[a-zA-Z0-9_\\-]+)/"
"(?P<lname>[a-zA-Z0-9_\\-]+)/?$",
helloworld.api.Greeting),
("/api/freewilled/?", helloworld.api.FreeWilledHandler)
])
assert sorted(routes.get_routes(
cars)) == sorted([
("/api/cars/?", cars.api.MakeListHandler),
("/api/cars/(?P<make>[a-zA-Z0-9_]+)/(?P<model>[a-zA-Z0-9_]+)/?$",
("/api/cars/(?P<make>[a-zA-Z0-9_\\-]+)/(?P<model>[a-zA-Z0-9_\\-]+)/?$",
cars.api.ModelHandler),
("/api/cars/(?P<make>[a-zA-Z0-9_]+)/(?P<model>[a-zA-Z0-9_]+)/"
"(?P<year>[a-zA-Z0-9_]+)/?$", cars.api.YearHandler),
("/api/cars/(?P<make>[a-zA-Z0-9_]+)/?$", cars.api.MakeHandler),
("/api/cars/(?P<make>[a-zA-Z0-9_\\-]+)/(?P<model>[a-zA-Z0-9_\\-]+)/"
"(?P<year>[a-zA-Z0-9_\\-]+)/?$", cars.api.YearHandler),
("/api/cars/(?P<make>[a-zA-Z0-9_\\-]+)/?$", cars.api.MakeHandler),
])

def test_gen_submodule_names(self):
Expand All @@ -75,11 +75,11 @@ def test_get_module_routes(self):
assert sorted(routes.get_module_routes(
"cars.api")) == sorted([
("/api/cars/?", cars.api.MakeListHandler),
("/api/cars/(?P<make>[a-zA-Z0-9_]+)/(?P<model>[a-zA-Z0-9_]+)/?$",
("/api/cars/(?P<make>[a-zA-Z0-9_\\-]+)/(?P<model>[a-zA-Z0-9_\\-]+)/?$",
cars.api.ModelHandler),
("/api/cars/(?P<make>[a-zA-Z0-9_]+)/(?P<model>[a-zA-Z0-9_]+)/"
"(?P<year>[a-zA-Z0-9_]+)/?$", cars.api.YearHandler),
("/api/cars/(?P<make>[a-zA-Z0-9_]+)/?$", cars.api.MakeHandler),
("/api/cars/(?P<make>[a-zA-Z0-9_\\-]+)/(?P<model>[a-zA-Z0-9_\\-]+)/"
"(?P<year>[a-zA-Z0-9_\\-]+)/?$", cars.api.YearHandler),
("/api/cars/(?P<make>[a-zA-Z0-9_\\-]+)/?$", cars.api.MakeHandler),
])


Expand Down
12 changes: 8 additions & 4 deletions tornado_json/routes.py
Expand Up @@ -41,7 +41,8 @@ def gen_submodule_names(package):
yield modname


def get_module_routes(module_name, custom_routes=None, exclusions=None):
def get_module_routes(module_name, custom_routes=None, exclusions=None,
arg_pattern=r'(?P<{}>[a-zA-Z0-9_\-]+)'):
"""Create and return routes for module_name

Routes are (url, RequestHandler) tuples
Expand All @@ -56,9 +57,10 @@ def get_module_routes(module_name, custom_routes=None, exclusions=None):
``/api/helloworld``.
Additionally, if a method has extra arguments aside from ``self`` in
its signature, routes with URL patterns will be generated to
match ``r"(?P<{}>[a-zA-Z0-9_]+)".format(argname)`` for each
match ``r"(?P<{}>[a-zA-Z0-9_\-]+)".format(argname)`` for each
argument. The aforementioned regex will match ONLY values
with alphanumeric+underscore characters.
with alphanumeric, hyphen and underscore characters. You can provide
your own pattern by setting a ``arg_pattern`` param.
:rtype: [(url, RequestHandler), ... ]
:type module_name: str
:param module_name: Name of the module to get routes for
Expand All @@ -68,6 +70,8 @@ def get_module_routes(module_name, custom_routes=None, exclusions=None):
:type exclusions: [str, str, ...]
:param exclusions: List of RequestHandler names that routes should not be
generated for
:type arg_pattern: str
:param arg_pattern: Default pattern for extra arguments of any method
"""
def has_method(module, cls_name, method_name):
return all([
Expand Down Expand Up @@ -126,7 +130,7 @@ def get_arg_route():
"""
if yield_args(module, cls_name, method_name):
return "/{}/?$".format("/".join(
["(?P<{}>[a-zA-Z0-9_]+)".format(argname) for argname
[arg_pattern.format(argname) for argname
in yield_args(module, cls_name, method_name)]
))
return r"/?"
Expand Down