Skip to main content

A WSGI dispatcher.

Project description

A WSGI dispatcher.

https://travis-ci.org/hirokiky/matcha.png

At a glance

matcha is a dispatcher for all WSGI application based on a matching pattern of PATH_INFO in environ.

Let’s register your WSGI applications to matchings and create WSGI application.

>>> from wsgiref.simple_server import make_server
>>> from matcha import Matching as m, bundle, make_wsgi_app
>>>
>>> from yourproject import home_app
>>> from yourproject.blog import post_list_app, post_detail_app
>>>
>>>
>>> matching = bundle(
...     m('/', home_app, 'home'),
...     m('/post/', post_list_app, 'post_list'),
...     m('/post/{post_slug}/', post_detail_app, 'post_detail'),
... )
>>>
>>> if __name__ == '__main__':
...     app = make_wsgi_app(matching)
...
...     httpd = make_server('', 8000, app)
...     httpd.serve_forever()

Now, accessing from your browser:

URL arguments

When path elements covered with braces, this handled as URL arguments. This path element can match any string and you can use that string in your WSGI application.

The URL arguments can get from environ[‘matcha.matched_dict’] in your WSGI application. For instance, accessing to ‘/post/hello_world/’, you can get ‘hello_world’ string as URL arguments like this:

>>> # In post_detail_app:
>>> environ['matcha.matched_dict']
{'post_slug': 'hello_world'}

Wildcard

If the last element in pattern starts with ‘*’, the following string is considered as wildcard_name. And correspond path will always match.

>>> matching = bundle(
    m('/', home_app, 'home'),
    m('/docs/*doc_tree', document_app, 'docs')
)

And then, you can access them:

After /docs/ it will match any cases.

And getting the argument.

>>> # In document_app, when accessed by '/docs/about/contributing'
>>> environ['matcha.mathed_dict']
{'doc_tree', ['about', 'contributing']}
>>> environ['PATH_INFO']
'/about/contributing'
>>> environ['SCRIPT_NAME']
'/docs'

You can also use this implementation to call another WSGI application such as dispatching again by using the left PATH_INFO

Reversing

Web pages usually contains some URLs for a another page. In this case, post list page is for showing URLs to each Blog posts (to post_detail application).

Let’s take URL to post_detail application. You can do like this:

>>> # In post_list_app
>>> matching = environ['matcha.matching']
>>> matching.reverse('post_detail', post_slug='about_matcha')
'/post/about_matcha/'
  • The first positional argument is a signature string for applications. It provided as the third argument of each Matching’s constructors.

  • The keyword argument is a string to fill up the URL arguments.

  • Careflly, reverse method will raise NotReverced exception when any URLs is not matched.

OK. and then, you can provide this URL to some TemplateEngines to display HTML pages.

Including another matchings

For more reusability, let’s separate applications for blogs from core matching.

# In yourproject/blog/matching.py file

from matcha import Matching as m, bundle

from yourproject.blog import post_list_app, post_detail_app


matching = bundle(
    m('/', post_list_app, 'post_list'),
    m('/{post_slug}/', post_detail_app, 'post_detail'),
)

And then, applying this to core by using include function:

>>> from matcha import include
>>> from yourproject.blog.matching import matching as blog_matching
>>>
>>> matching = bundle(
...     m('/', home_app, 'home'),
...     include('/post/', blog_matching)
... )

Matching paths will be like this:

  • / => home application

  • /post/ => post_list application

  • /post/some_slug/ => post_detail application

By using include, you can separate paths based on each applications and avoid repeating of descriptions (such as ‘/post/’).

Name for reverisng to childs are not affected in any way. This value should be unique, even in the all of matchings (fixed in matcha 0.3):

>>> matching.reverse('post_detail', post_slug='some_slug')
'/post/some_slug/'

Setting your 404 WSGI application

The path matching failed the maked application by matcha will return a plain 404 page. But most cases, you want to custorm this page more friendly for users.

For solving this, matcha.make_wsgi_app can take not_found_app keyword argument to provide your own WSGI application for showing 404 page.

By default, the not_found_app is matcha.not_found_app.

What is Matching objects

Almost core features provided by matcha dispatcher is implamented as Matching objects.

Now, through above example, you recognize matching is like this:

  • matching is created by using bundle function and Matching class.

  • Registering WSGI apllications to matching.

  • matching can get from environ dictionaly

Not wrong, but Matching class is something more flexible than your recognition.

Calling

matching is callable

  • taking environ dictionary

  • sideeffecting environ dictionary

  • returning matched case and dictionary

That sideeffection is for PATH_INFO and SCRIPT_NAME to tell which path elements are processed to another WSGI application.

>>> environ = {'PATH_INFO': '/htt', 'SCRIPT_NAME': '/about'}
>>> Matching('/htt', about_htt_app)(environ)
(about_htt_app, {})
>>> environ
{'PATH_INFO': '', 'SCRIPT_NAME': '/about/htt'}

Getitem from matching

cailling of matching requires environ dictionaly, but using getitem you can only apply path to get matched case and dictionaly.

>>> Matching('/htt', about_htt_app)['/htt']
(about_htt_app, {})

Registering not only WSGI app

Second positional argument (case keyword argument) of Matching class can take any objects you like, not only WSGI app.

>>> Matching('/home', 'home')['/home']
('home', {})

For instance, you can register strings and use this as signature for some views. something like route_name on Pyramid.

Adding matchings

Actually, bundle function used in above examples is just for adding provided positional arguments (addable objects). So you can make WSGI application without this function:

>>> app = make_wsgi_app(
...     Matching('/', home_app) + \
...     Matching('/abount', about_app)
... )

Thanks

matcha dispatcher has been influenced these dispatchers:

Thanks for them.

Resources

Changes

0.3

Un-supporting name argument on include function

Before this change, user applied include name, the reversing in included app will break, because the name for reversing already changed.

0.2

  • Supporting Wildcard

0.1

Initial release.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

matcha-0.3.tar.gz (6.4 kB view hashes)

Uploaded Source

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page