New in version 1.1.0.
Model-View-Controller-based sub-framework.
This module and it’s sub-modules constitutes the most common way of using Smisk, mapping URLs to the control tree – an actual class tree, growing from smisk.mvc.control.Controller.
Key members
Example:
from smisk.mvc import *
class root(Controller):
def __call__(self, *args, **params):
return {'message': 'Hello World!'}
main()
Name of a default response serializer.
The value should be the name of a serializer extension (the value should be a valid key in the smisk.serialization.serializers.extensions dictionary).
If not set, the Response.fallback_serializer will be used for clients not requesting any particular content type.
Default: | None |
---|---|
Type: | str |
Enables adding an ETag header to all buffered responses.
The value needs to be either the name of a valid hash function in the hashlib module (i.e. “md5”), or a something respoding in the same way as the hash functions in hashlib. i.e. need to return a hexadecimal string rep when:
h = etag(data)
h.update(more_data)
etag_value = h.hexdigest()
Enabling this is generally not recommended as it introduces a small to moderate performance hit, because a checksum need to be calculated for each response, and because of the nature of the data Smisk does not know about all stakes in a transaction, thus constructing a valid ETag might somethimes be impossible.
Default: | None |
---|---|
Type: | str |
Controls whether or not this application is strict about transparent content negotiation.
For example, if this is True and a client accepts a character encoding which is not available, a 206 Not Acceptable response is sent. If the value would have been False, the response would be sent using a data encoder default character set.
This affects Accept* request headers which demands can not be met.
As HTTP 1.1 (RFC 2616) allows fallback to defaults (though not recommended) we provide the option of turning off the 206 response. Setting this to false will cause Smisk to encode text responses using a best-guess character encoding.
Default: | True |
---|---|
Type: | bool |
A leaf filter is basically code that is run prior to and after calling a leaf on the controller tree, allowing manipulation of input, output and the states of things.
Let’s have a look at an example filter which gives the ability to say “this leaf requires a logged in user”:
from smisk.mvc.decorators import leaf_filter
@leaf_filter
def require_login(leaf, *va, **kw):
if not request.session or not request.session.get('userid'):
redirect_to(root.login)
return leaf(*va, **kw)
This filter requires a valid session and the key userid to be set in the session (in this case things are simplified for educational reasons — in reality we would probably check the type of the session object also).
And here is how you would use the filter above:
class root(Controller):
@require_login
def protected(self):
return {'secret launch codes': [u'abc', 123]}
def login(self):
pass # (actual auth code here)
# curl localhost:8080/protected
# 302 Found -> http://localhost:8080/login
Note that the from smisk.mvc.decorators import leaf_filter is not needed if you are importing everything from smisk.mvc since leaf_filter is also exported from smisk.mvc.
For more information and examples see smisk.mvc.filters and smisk.mvc.decorators.leaf_filter().
Name of the current environment.
Returns the value of SMISK_ENVIRONMENT environment value and defaults to “stable“.
Helper for setting up and running an application.
This function is not a true function, but rather an instance of Main.
See documentation of smisk.util.main.main() for more information.
Helper for running an application.
Note that because of the nature of libfcgi an application can not be started, stopped and then started again. That said, you can only start your application once per process. (Details: OS_ShutdownPending sets a process-wide flag causing any call to accept to bail out)
Environment variables
Parameters: |
|
---|---|
Returns: | Anything returned by Application.run() |
Return type: | object |
See: |
Deprecated: | You should use smisk.util.main.Main.setup() instead. |
---|
See: | Documentation of smisk.util.main.Main |
---|
MVC application
See: | smisk.core.Application |
---|
Templates handler.
If this evaluates to false, templates are disabled.
See: | __init__() |
---|---|
Type: | Templates |
Router.
Type: | Router |
---|
Used during runtime. Here because we want to use it in error()
Type: | Serializer |
---|
Used during runtime. Available in actions, serializers and templates.
Type: | routing.Destination |
---|
Used during runtime.
Type: | mako.template.Template |
---|
How to handle unicode conversions.
Possible values: strict, ignore, replace, xmlcharrefreplace, backslashreplace
Type: | string |
---|
Automatically clear the model session cache before each request is handled.
You should not disable this unless any of the following statements apply:
Disabling this means entities stay in the local memory cache between sessions. (Relations and their content etc are cached, but not the actual data in the entities)
Consider this model:
class Department(Entity):
people = OneToMany('Person')
class Person(Entity):
department = ManyToOne('Department')
Now, imagine we have two processes running; process A and process B. Process A gets a request to add a new person to an existing department. Afterwards, process B is requested to list all people in the same department. Now, if autoclear_model_session where set to False, the previously added person would no show up in the listing of people in the department which process B queried. This is because which people is “contained within” what department has been implicitly cached by SQLAlchemy.
Type: | bool |
---|---|
Default: | True |
Application-global leaf filters, applied to all leafs in the controller tree.
The filter are applied in the order they appear in this list.
from smisk.mvc import *
@leaf_filter
def ensure_page_title(leaf, *va, **kw):
rsp = leaf(*va, **kw)
rsp.setdefault('title', u'The Title')
return rsp
class App(Application):
def application_will_start(self):
self.leaf_filters.append(ensure_page_title)
return Application.application_will_start(self)
Type: | list |
---|
New in version 1.1.3.
Automatically load configuration from application sub-module named config_mod_name.
Parameters: |
|
---|
Resolves and calls the appropriate action, passing args and params to it.
Returns: | Response structure or None |
---|
Encode the response object rsp
Parameters: |
|
---|---|
Returns: | rsp encoded as a series of bytes |
See: |
Handle an error and produce an appropriate response.
Parameters: |
|
---|
Parses the request, involving appropriate serializer if needed.
Returns: | (list arguments, dict parameters) |
---|---|
Return type: | tuple |
Return the most appropriate serializer for handling response encoding.
Parameters: |
|
---|---|
Returns: | The most appropriate serializer |
Return type: |
Send the response to the current client, finalizing the current HTTP transaction.
Parameters: |
|
---|---|
See: |
Manages the life of a HTTP transaction.
Summary
Setup application state.
Can be called multiple times and is automatically called, just after calling autoload_configuration(), by setup() and application_will_start().
Outline
Aquire template URI for path.
Parameters: |
|
---|---|
Return type: | template.Template |
Aquire template for uri.
Parameters: |
|
---|---|
Return type: | template.Template |
Get template URI for path.
Parameters: |
|
---|---|
Return type: | string |
Serializer used for decoding request payload.
Available during a HTTP transaction.
Type: | smisk.serialization.Serializer |
---|
New in version 1.1.3.
URL with any filename extension removed, for use with Content Negotiation.
If the request did not contain a filename extension, this is the same object as smisk.core.Request.url.
Type: | smisk.core.URL |
---|
Any value which is a valid key of the smisk.serializers.extensions dict.
Type: | string |
---|
Serializer to use for encoding the response.
The class attribute value serves as the application default serializer, used in cases where we need to encode the response, but the client is not specific about which serializer to use.
If None, strict TCN applies.
See: | fallback_serializer |
---|---|
Type: | smisk.serialization.Serializer |
Last-resort serializer, used for error responses and etc.
If None when Application.application_will_start is called, this will be set to a HTML-serializer, and if none is available, simply the first registered serializer will be used.
The class property is the only one used, the instance property has no meaning and no effect, thus if you want to modify this during runtime, you should do this Response.fallback_serializer = my_serializer instead of this app.response.fallback_serializer = my_serializer.
Type: | smisk.serialization.Serializer |
---|
Character encoding used to encode the response body.
The value of Response.charset (class property value) serves as the application default charset.
Type: | string |
---|
Send a file to the client by using the host server sendfile-header technique.
Automatically sets Content-Type header, using mimetypes.guess_type
Calling this method implicitly commits the current HTTP transaction, sending the response immedately.
Parameters: |
|
---|---|
Raises EnvironmentError: | |
If smisk does not know how to perform sendfile through the current host server. |
|
Raises EnvironmentError: | |
If response has already started. |
|
Raises IOError: |
New in version 1.1.1.
Make sure appropriate status is set for the response.
New in version 1.1.1.
Remove any instance of header named or prefixed name.
New in version 1.1.1.
Remove any instance of headers named or prefixed *names.
New in version 1.1.1.
Replace any instances of the same header type with header.
>>> response.headers
[]
>>> response.headers.append('Content-Type: text/humbug')
>>> response.headers.append('X-Name: Fuffens')
>>> response.headers
['Content-Type: text/humbug', 'X-Name: Fuffens']
>>> response.replace_header('Content-type: text/plain')
>>> response.headers
['X-Name: Fuffens', 'Content-type: text/plain']