~barry/mailman/events-and-web

« back to all changes in this revision

Viewing changes to src/mailman/rest/helpers.py

  • Committer: Barry Warsaw
  • Date: 2012-09-22 17:35:24 UTC
  • Revision ID: barry@list.org-20120922173524-55hz5ltrdzukupdt
 * You can now PUT and PATCH on user resources to change the user's display
   name or password.  For passwords, you pass in the clear text password and
   Mailman will hash it before storing.

Also:

 * Major refactoring of validators for PUT and PATCH.  Pull the common logic
   out of configuration.py and put it in a PatchValidator class in
   helpers.py.  Also move GetterSetter to helpers.py
 * Add new exception classes RESTError, UnknownPATCHRequestError,
   ReadOnlyPATCHRequestError.  These are used in the PatchValidator.
 * Added Validator.update() which works nicely for PATCH and PUT.

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
 
22
22
__metaclass__ = type
23
23
__all__ = [
 
24
    'GetterSetter',
24
25
    'PATCH',
25
26
    'etag',
26
27
    'no_content',
205
206
    def __call__(self, func):
206
207
        really_wrapped_func = PATCHWrapper(func)
207
208
        return super(PATCH, self).__call__(really_wrapped_func)
 
209
 
 
210
 
 
211
class GetterSetter:
 
212
    """Get and set attributes on an object.
 
213
 
 
214
    Most attributes are fairly simple - a getattr() or setattr() on the object
 
215
    does the trick, with the appropriate encoding or decoding on the way in
 
216
    and out.  Encoding doesn't happen here though; the standard JSON library
 
217
    handles most types, but see ExtendedEncoder for additional support.
 
218
 
 
219
    Others are more complicated since they aren't kept in the model as direct
 
220
    columns in the database.  These will use subclasses of this base class.
 
221
    Read-only attributes will have a decoder which always raises ValueError.
 
222
    """
 
223
 
 
224
    def __init__(self, decoder=None):
 
225
        """Create a getter/setter for a specific attribute.
 
226
 
 
227
        :param decoder: The callable for decoding a web request value string
 
228
            into the specific data type needed by the object's attribute.  Use
 
229
            None to indicate a read-only attribute.  The callable should raise
 
230
            ValueError when the web request value cannot be converted.
 
231
        :type decoder: callable
 
232
        """
 
233
        self.decoder = decoder
 
234
 
 
235
    def get(self, obj, attribute):
 
236
        """Return the named object attribute value.
 
237
 
 
238
        :param obj: The object to access.
 
239
        :type obj: object
 
240
        :param attribute: The attribute name.
 
241
        :type attribute: string
 
242
        :return: The attribute value, ready for JSON encoding.
 
243
        :rtype: object
 
244
        """
 
245
        return getattr(obj, attribute)
 
246
 
 
247
    def put(self, obj, attribute, value):
 
248
        """Set the named object attribute value.
 
249
 
 
250
        :param obj: The object to change.
 
251
        :type obj: object
 
252
        :param attribute: The attribute name.
 
253
        :type attribute: string
 
254
        :param value: The new value for the attribute.
 
255
        """
 
256
        setattr(obj, attribute, value)
 
257
 
 
258
    def __call__(self, value):
 
259
        """Convert the value to its internal format.
 
260
 
 
261
        :param value: The web request value to convert.
 
262
        :type value: string
 
263
        :return: The converted value.
 
264
        :rtype: object
 
265
        """
 
266
        if self.decoder is None:
 
267
            return value
 
268
        return self.decoder(value)