Coverage for /home/martinb/.local/share/virtualenvs/camcops/lib/python3.6/site-packages/deform/schema.py : 37%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""Schema."""
2# Pyramid
3import colander
5# Deform
6from deform.i18n import _
8from . import widget
11default_widget_makers = {
12 colander.Mapping: widget.MappingWidget,
13 colander.Sequence: widget.SequenceWidget,
14 colander.String: widget.TextInputWidget,
15 colander.Integer: widget.TextInputWidget,
16 colander.Float: widget.TextInputWidget,
17 colander.Decimal: widget.TextInputWidget,
18 colander.Boolean: widget.CheckboxWidget,
19 colander.Date: widget.DateInputWidget,
20 colander.DateTime: widget.DateTimeInputWidget,
21 colander.Tuple: widget.TextInputCSVWidget,
22 colander.Time: widget.TimeInputWidget,
23 colander.Money: widget.MoneyInputWidget,
24 colander.Set: widget.CheckboxChoiceWidget,
25}
28@colander.deferred
29def deferred_csrf_value(node, kw):
30 return kw["request"].session.get_csrf_token()
33class FileData(object):
34 """
35 A type representing file data; used to shuttle data back and forth
36 between an application and the
37 :class:`deform.widget.FileUploadWidget` widget.
39 This type passes the value obtained during deserialization back to
40 the caller unchanged (it will be an instance of
41 ``deform.widget.filedict``, which is a plain dictionary subclass;
42 it is only a dict subclass so ``isinstance`` may be used against
43 it in highly generalized persistence circumstances to detect that
44 it is file data). It serializes from a dictionary containing
45 partial file data info into a dictionary containing full file data
46 info, serializing the full file data (the widget receives the full
47 file data).
48 """
50 # We cant use FileUploadWidget as the default_widget_maker for
51 # this schema node because it requires a tmpstore argument, and
52 # a tmpstore cannot be generally defaulted.
54 def serialize(self, node, value):
55 """
56 Serialize a dictionary representing partial file information
57 to a dictionary containing information expected by a file
58 upload widget.
60 The file data dictionary passed as ``value`` to this
61 ``serialize`` method *must* include:
63 filename
64 Filename of this file (not a full filesystem path, just the
65 filename itself).
67 uid
68 Unique string id for this file. Needs to be unique enough to
69 disambiguate it from other files that may use the same
70 temporary storage mechanism before a successful validation,
71 and must be adequate for the calling code to reidentify it
72 after deserialization.
74 A fully populated dictionary *may* also include the following
75 values:
77 fp
78 File-like object representing this file's content or
79 ``None``. ``None`` indicates this file has already been
80 committed to permanent storage. When serializing a
81 'committed' file, the ``fp`` value should ideally not be
82 passed or it should be passed as ``None``; ``None`` as an
83 ``fp`` value is a signifier to the file upload widget that
84 the file data has already been committed. Using ``None``
85 as an ``fp`` value helps prevent unnecessary data copies
86 to temporary storage when a form is rendered, however its
87 use requires cooperation from the calling code; in
88 particular, the calling code must be willing to translate
89 a ``None`` ``fp`` value returned from a deserialization
90 into the file data via the ``uid`` in the deserialization.
92 mimetype
93 File content type (e.g. ``application/octet-stream``).
95 size
96 File content length (integer).
98 preview_url
99 URL which provides an image preview of this file's data.
101 If a ``size`` is not provided, the widget will have no access
102 to size display data. If ``preview_url`` is not provided, the
103 widget will not be able to show a file preview. If
104 ``mimetype`` is not provided, the widget will not be able to
105 display mimetype information.
106 """
107 if value is colander.null:
108 return colander.null
110 if not hasattr(value, "get"):
111 mapping = {"value": repr(value)}
112 raise colander.Invalid(
113 node, _("${value} is not a dictionary", mapping=mapping)
114 )
115 for n in ("filename", "uid"):
116 if n not in value:
117 mapping = {"value": repr(value), "key": n}
118 raise colander.Invalid(
119 node, _("${value} has no ${key} key", mapping=mapping)
120 )
121 result = widget.filedict(value)
122 # provide a value for these entries even if None
123 result["mimetype"] = value.get("mimetype")
124 result["size"] = value.get("size")
125 result["fp"] = value.get("fp")
126 result["preview_url"] = value.get("preview_url")
127 return result
129 def deserialize(self, node, value):
130 return value
132 def cstruct_children(self, node, cstruct): # pragma: no cover
133 return []
136class CSRFSchema(colander.Schema):
137 """
138 CSRF protected form schema.
140 Example:
142 .. code-block:: python
144 import colander
145 from deform.schema import CSRFSchema
147 class MySchema(CSRFSchema):
148 my_field = colander.SchemaNode(colander.String())
150 And in your application code, *bind* the schema, passing the request as a
151 keyword argument:
153 .. code-block:: python
155 def view(request):
156 schema = MySchema().bind(request=request)
158 When using Pyramid 1.7+, the CSRF token is validated by CSRF view deriver.
160 More information
162 https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/sessions.html#checking-csrf-tokens-automatically # noqa: E501
163 """
165 csrf_token = colander.SchemaNode(
166 colander.String(),
167 widget=widget.HiddenWidget(),
168 default=deferred_csrf_value,
169 )