Show More
@@ -25,6 +25,46 def sort_key(model): | |||||
25 | }.get(model['type'], '9') |
|
25 | }.get(model['type'], '9') | |
26 | return u'%s%s' % (type_key, iname) |
|
26 | return u'%s%s' % (type_key, iname) | |
27 |
|
27 | |||
|
28 | ||||
|
29 | def validate_model(model, expect_content): | |||
|
30 | required_keys = { | |||
|
31 | "name" | |||
|
32 | , "path" | |||
|
33 | , "type" | |||
|
34 | , "writable" | |||
|
35 | , "created" | |||
|
36 | # Note: This key is specified as just 'modified' in IPEP-27 | |||
|
37 | , "last_modified" | |||
|
38 | , "mimetype" | |||
|
39 | , "content" | |||
|
40 | , "format" | |||
|
41 | } | |||
|
42 | missing = required_keys - set(model.keys()) | |||
|
43 | if missing: | |||
|
44 | raise web.HTTPError( | |||
|
45 | 500, | |||
|
46 | u"Missing Model Keys: {missing}".format(missing=missing), | |||
|
47 | ) | |||
|
48 | ||||
|
49 | # Note: Per IPEP-27, 'mimetype' should be present in this list. | |||
|
50 | maybe_none_keys = ['content', 'format'] | |||
|
51 | if expect_content: | |||
|
52 | errors = [key for key in maybe_none_keys if model[key] is None] | |||
|
53 | if errors: | |||
|
54 | raise web.HTTPError( | |||
|
55 | 500, | |||
|
56 | u"Keys unexpectedly None: {keys}".format(keys=errors), | |||
|
57 | ) | |||
|
58 | ||||
|
59 | else: | |||
|
60 | errors = [key for key in maybe_none_keys if model[key] is not None] | |||
|
61 | if errors: | |||
|
62 | raise web.HTTPError( | |||
|
63 | 500, | |||
|
64 | u"Keys unexpectedly not None: {keys}".format(keys=errors), | |||
|
65 | ) | |||
|
66 | ||||
|
67 | ||||
28 | class ContentsHandler(IPythonHandler): |
|
68 | class ContentsHandler(IPythonHandler): | |
29 |
|
69 | |||
30 | SUPPORTED_METHODS = (u'GET', u'PUT', u'PATCH', u'POST', u'DELETE') |
|
70 | SUPPORTED_METHODS = (u'GET', u'PUT', u'PATCH', u'POST', u'DELETE') | |
@@ -72,6 +112,7 class ContentsHandler(IPythonHandler): | |||||
72 | # group listing by type, then by name (case-insensitive) |
|
112 | # group listing by type, then by name (case-insensitive) | |
73 | # FIXME: sorting should be done in the frontends |
|
113 | # FIXME: sorting should be done in the frontends | |
74 | model['content'].sort(key=sort_key) |
|
114 | model['content'].sort(key=sort_key) | |
|
115 | validate_model(model, expect_content=True) | |||
75 | self._finish_model(model, location=False) |
|
116 | self._finish_model(model, location=False) | |
76 |
|
117 | |||
77 | @web.authenticated |
|
118 | @web.authenticated | |
@@ -83,6 +124,7 class ContentsHandler(IPythonHandler): | |||||
83 | if model is None: |
|
124 | if model is None: | |
84 | raise web.HTTPError(400, u'JSON body missing') |
|
125 | raise web.HTTPError(400, u'JSON body missing') | |
85 | model = cm.update(model, path) |
|
126 | model = cm.update(model, path) | |
|
127 | validate_model(model, expect_content=False) | |||
86 | self._finish_model(model) |
|
128 | self._finish_model(model) | |
87 |
|
129 | |||
88 | def _copy(self, copy_from, copy_to=None): |
|
130 | def _copy(self, copy_from, copy_to=None): | |
@@ -93,6 +135,7 class ContentsHandler(IPythonHandler): | |||||
93 | )) |
|
135 | )) | |
94 | model = self.contents_manager.copy(copy_from, copy_to) |
|
136 | model = self.contents_manager.copy(copy_from, copy_to) | |
95 | self.set_status(201) |
|
137 | self.set_status(201) | |
|
138 | validate_model(model, expect_content=False) | |||
96 | self._finish_model(model) |
|
139 | self._finish_model(model) | |
97 |
|
140 | |||
98 | def _upload(self, model, path): |
|
141 | def _upload(self, model, path): | |
@@ -100,6 +143,7 class ContentsHandler(IPythonHandler): | |||||
100 | self.log.info(u"Uploading file to %s", path) |
|
143 | self.log.info(u"Uploading file to %s", path) | |
101 | model = self.contents_manager.new(model, path) |
|
144 | model = self.contents_manager.new(model, path) | |
102 | self.set_status(201) |
|
145 | self.set_status(201) | |
|
146 | validate_model(model, expect_content=False) | |||
103 | self._finish_model(model) |
|
147 | self._finish_model(model) | |
104 |
|
148 | |||
105 | def _new_untitled(self, path, type='', ext=''): |
|
149 | def _new_untitled(self, path, type='', ext=''): | |
@@ -107,12 +151,14 class ContentsHandler(IPythonHandler): | |||||
107 | self.log.info(u"Creating new %s in %s", type or 'file', path) |
|
151 | self.log.info(u"Creating new %s in %s", type or 'file', path) | |
108 | model = self.contents_manager.new_untitled(path=path, type=type, ext=ext) |
|
152 | model = self.contents_manager.new_untitled(path=path, type=type, ext=ext) | |
109 | self.set_status(201) |
|
153 | self.set_status(201) | |
|
154 | validate_model(model, expect_content=False) | |||
110 | self._finish_model(model) |
|
155 | self._finish_model(model) | |
111 |
|
156 | |||
112 | def _save(self, model, path): |
|
157 | def _save(self, model, path): | |
113 | """Save an existing file.""" |
|
158 | """Save an existing file.""" | |
114 | self.log.info(u"Saving file at %s", path) |
|
159 | self.log.info(u"Saving file at %s", path) | |
115 | model = self.contents_manager.save(model, path) |
|
160 | model = self.contents_manager.save(model, path) | |
|
161 | validate_model(model, expect_content=False) | |||
116 | self._finish_model(model) |
|
162 | self._finish_model(model) | |
117 |
|
163 | |||
118 | @web.authenticated |
|
164 | @web.authenticated |
General Comments 0
You need to be logged in to leave comments.
Login now