forked from devilry/devilry-django
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
devilry|devilry_rest: Moved rest stuff from devilry.utils to devilry_…
…rest. Kept the modules in devilry.utils, with deprecation warnings.
- Loading branch information
Showing
8 changed files
with
187 additions
and
172 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,43 +1,3 @@ | ||
from django.test import Client | ||
import json | ||
|
||
|
||
class RestClient(Client): | ||
""" | ||
Extends the ``django.test.Client`` with methods for the REST verbs and | ||
application/json. | ||
""" | ||
|
||
def _load_json(self, content): | ||
if content.strip() == '': | ||
return None | ||
try: | ||
return json.loads(content) | ||
except ValueError, e: | ||
raise ValueError('{0}: {1}'.format(e, content)) | ||
|
||
def rest_post(self, url, data): | ||
response = self.post(url, | ||
data=json.dumps(data), | ||
content_type="application/json", | ||
HTTP_ACCEPT="application/json") | ||
return self._load_json(response.content), response | ||
|
||
def rest_put(self, url, data, **extra): | ||
response = self.put(url, | ||
data=json.dumps(data), | ||
content_type="application/json", | ||
HTTP_ACCEPT="application/json", | ||
**extra) | ||
return self._load_json(response.content), response | ||
|
||
def rest_get(self, url, **data): | ||
response = self.get(url, | ||
data=data, | ||
HTTP_ACCEPT="application/json") | ||
return self._load_json(response.content), response | ||
|
||
def rest_delete(self, url): | ||
response = self.delete(url, | ||
HTTP_ACCEPT="application/json") | ||
return self._load_json(response.content), response | ||
import warnings | ||
warnings.warn("devilry.utils.rest_testclient is deprecated. Use devilry_rest.testclient instead.", DeprecationWarning) | ||
from devilry_rest.testclient import RestClient |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,5 @@ | ||
def format_datetime(datetime): | ||
return datetime.strftime('%Y-%m-%d %H:%M:%S') | ||
|
||
def format_timedelta(timedelta_obj): | ||
total_seconds = abs(timedelta_obj.total_seconds()) | ||
days, remainder = divmod(total_seconds, 86400) | ||
hours, remainder = divmod(remainder, 3600) | ||
minutes, seconds = divmod(remainder, 60) | ||
return {'days': int(days), | ||
'hours': int(hours), | ||
'minutes': int(minutes), | ||
'seconds': int(seconds)} | ||
|
||
def serialize_user(user): | ||
return {'id': user.id, | ||
'username': user.username, | ||
'email': user.email, | ||
'displayname': user.devilryuserprofile.full_name or user.username, | ||
'full_name': user.devilryuserprofile.full_name} | ||
import warnings | ||
warnings.warn("devilry.utils.restformat is deprecated. Use devilry_rest.serializehelpers instead.", DeprecationWarning) | ||
from devilry_rest.serializehelpers import format_datetime | ||
from devilry_rest.serializehelpers import format_timedelta | ||
from devilry_rest.serializehelpers import serialize_user |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,109 +1,5 @@ | ||
""" | ||
Form fields that are useful only for REST APIs. | ||
""" | ||
from django import forms | ||
from django.core.exceptions import ValidationError | ||
|
||
|
||
class ListOfDictField(forms.Field): | ||
|
||
def validate_to_python(self, value): | ||
""" | ||
Validate and clean data. | ||
""" | ||
super(ListOfDictField, self).validate(value) | ||
if value == None: | ||
return [] | ||
if not isinstance(value, (list, tuple)): | ||
raise ValidationError('Must be a list or tuple, got {0}'.format(type(value).__name__)) | ||
cleaned = [] | ||
for index, dct in enumerate(value): | ||
if not isinstance(dct, dict): | ||
raise ValidationError('Item {0}: Must be a list of dicts, got {1}'.format(index, type(value))) | ||
form = self.Form(dct) | ||
if form.is_valid(): | ||
cleaned.append(form.cleaned_data) | ||
else: | ||
errors = form.errors.as_text() | ||
raise ValidationError('Item {0}: Invalid format:\n{1}'.format(index, errors)) | ||
return cleaned | ||
|
||
def clean(self, value): | ||
""" | ||
Validates the given value and returns its "cleaned" value as an | ||
appropriate Python object. | ||
Raises ValidationError for any errors. | ||
""" | ||
value = self.validate_to_python(value) | ||
self.run_validators(value) | ||
return value | ||
|
||
class DictField(forms.Field): | ||
|
||
def validate_to_python(self, value): | ||
""" | ||
Validate and clean data. | ||
""" | ||
super(DictField, self).validate(value) | ||
if value == None: | ||
return {} | ||
if not isinstance(value, dict): | ||
raise ValidationError('Must be a dict, got {0}'.format(type(value).__name__)) | ||
form = self.Form(value) | ||
if form.is_valid(): | ||
return form.cleaned_data | ||
else: | ||
errors = form.errors.as_text() | ||
raise ValidationError(errors) | ||
|
||
def clean(self, value): | ||
""" | ||
Validates the given value and returns its "cleaned" value as an | ||
appropriate Python object. | ||
Raises ValidationError for any errors. | ||
""" | ||
value = self.validate_to_python(value) | ||
self.run_validators(value) | ||
return value | ||
|
||
|
||
class ListOfTypedField(forms.Field): | ||
def __init__(self, *args, **kwargs): | ||
""" | ||
A field similar to TypedChoiceField that takes a list of items and a | ||
``coerce`` function that is applied to all items in the given list. | ||
""" | ||
self.coerce = kwargs.pop('coerce', id) | ||
super(ListOfTypedField, self).__init__(*args, **kwargs) | ||
|
||
def validate_to_python(self, valuelist): | ||
""" | ||
Validate and clean data. | ||
""" | ||
super(ListOfTypedField, self).validate(valuelist) | ||
if valuelist == None: | ||
return [] | ||
if not isinstance(valuelist, (list, tuple)): | ||
raise ValidationError('Must be a list or tuple, got {0}'.format(type(valuelist).__name__)) | ||
cleaned = [] | ||
for index, value in enumerate(valuelist): | ||
try: | ||
cleaned_value = self.coerce(value) | ||
except ValueError, e: | ||
raise ValidationError('Item {0}: {1}', index, e) | ||
else: | ||
cleaned.append(cleaned_value) | ||
return cleaned | ||
|
||
def clean(self, value): | ||
""" | ||
Validates the given value and returns its "cleaned" value as an | ||
appropriate Python object. | ||
Raises ValidationError for any errors. | ||
""" | ||
value = self.validate_to_python(value) | ||
self.run_validators(value) | ||
return value | ||
import warnings | ||
warnings.warn("devilry.utils.restformfields is deprecated. Use devilry_rest.formfields instead.", DeprecationWarning) | ||
from devilry_rest.formfields import ListOfDictField | ||
from devilry_rest.formfields import DictField | ||
from devilry_rest.formfields import ListOfTypedField |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
""" | ||
Form fields that are useful only for REST APIs. | ||
""" | ||
from django import forms | ||
from django.core.exceptions import ValidationError | ||
|
||
|
||
class ListOfDictField(forms.Field): | ||
|
||
def validate_to_python(self, value): | ||
""" | ||
Validate and clean data. | ||
""" | ||
super(ListOfDictField, self).validate(value) | ||
if value == None: | ||
return [] | ||
if not isinstance(value, (list, tuple)): | ||
raise ValidationError('Must be a list or tuple, got {0}'.format(type(value).__name__)) | ||
cleaned = [] | ||
for index, dct in enumerate(value): | ||
if not isinstance(dct, dict): | ||
raise ValidationError('Item {0}: Must be a list of dicts, got {1}'.format(index, type(value))) | ||
form = self.Form(dct) | ||
if form.is_valid(): | ||
cleaned.append(form.cleaned_data) | ||
else: | ||
errors = form.errors.as_text() | ||
raise ValidationError('Item {0}: Invalid format:\n{1}'.format(index, errors)) | ||
return cleaned | ||
|
||
def clean(self, value): | ||
""" | ||
Validates the given value and returns its "cleaned" value as an | ||
appropriate Python object. | ||
Raises ValidationError for any errors. | ||
""" | ||
value = self.validate_to_python(value) | ||
self.run_validators(value) | ||
return value | ||
|
||
class DictField(forms.Field): | ||
|
||
def validate_to_python(self, value): | ||
""" | ||
Validate and clean data. | ||
""" | ||
super(DictField, self).validate(value) | ||
if value == None: | ||
return {} | ||
if not isinstance(value, dict): | ||
raise ValidationError('Must be a dict, got {0}'.format(type(value).__name__)) | ||
form = self.Form(value) | ||
if form.is_valid(): | ||
return form.cleaned_data | ||
else: | ||
errors = form.errors.as_text() | ||
raise ValidationError(errors) | ||
|
||
def clean(self, value): | ||
""" | ||
Validates the given value and returns its "cleaned" value as an | ||
appropriate Python object. | ||
Raises ValidationError for any errors. | ||
""" | ||
value = self.validate_to_python(value) | ||
self.run_validators(value) | ||
return value | ||
|
||
|
||
class ListOfTypedField(forms.Field): | ||
def __init__(self, *args, **kwargs): | ||
""" | ||
A field similar to TypedChoiceField that takes a list of items and a | ||
``coerce`` function that is applied to all items in the given list. | ||
""" | ||
self.coerce = kwargs.pop('coerce', id) | ||
super(ListOfTypedField, self).__init__(*args, **kwargs) | ||
|
||
def validate_to_python(self, valuelist): | ||
""" | ||
Validate and clean data. | ||
""" | ||
super(ListOfTypedField, self).validate(valuelist) | ||
if valuelist == None: | ||
return [] | ||
if not isinstance(valuelist, (list, tuple)): | ||
raise ValidationError('Must be a list or tuple, got {0}'.format(type(valuelist).__name__)) | ||
cleaned = [] | ||
for index, value in enumerate(valuelist): | ||
try: | ||
cleaned_value = self.coerce(value) | ||
except ValueError, e: | ||
raise ValidationError('Item {0}: {1}', index, e) | ||
else: | ||
cleaned.append(cleaned_value) | ||
return cleaned | ||
|
||
def clean(self, value): | ||
""" | ||
Validates the given value and returns its "cleaned" value as an | ||
appropriate Python object. | ||
Raises ValidationError for any errors. | ||
""" | ||
value = self.validate_to_python(value) | ||
self.run_validators(value) | ||
return value | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
def format_datetime(datetime): | ||
return datetime.strftime('%Y-%m-%d %H:%M:%S') | ||
|
||
def format_timedelta(timedelta_obj): | ||
total_seconds = abs(timedelta_obj.total_seconds()) | ||
days, remainder = divmod(total_seconds, 86400) | ||
hours, remainder = divmod(remainder, 3600) | ||
minutes, seconds = divmod(remainder, 60) | ||
return {'days': int(days), | ||
'hours': int(hours), | ||
'minutes': int(minutes), | ||
'seconds': int(seconds)} | ||
|
||
def serialize_user(user): | ||
return {'id': user.id, | ||
'username': user.username, | ||
'email': user.email, | ||
'displayname': user.devilryuserprofile.full_name or user.username, | ||
'full_name': user.devilryuserprofile.full_name} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
from django.test import Client | ||
import json | ||
|
||
|
||
class RestClient(Client): | ||
""" | ||
Extends the ``django.test.Client`` with methods for the REST verbs and | ||
application/json. | ||
""" | ||
|
||
def _load_json(self, content): | ||
if content.strip() == '': | ||
return None | ||
try: | ||
return json.loads(content) | ||
except ValueError, e: | ||
raise ValueError('{0}: {1}'.format(e, content)) | ||
|
||
def rest_post(self, url, data): | ||
response = self.post(url, | ||
data=json.dumps(data), | ||
content_type="application/json", | ||
HTTP_ACCEPT="application/json") | ||
return self._load_json(response.content), response | ||
|
||
def rest_put(self, url, data, **extra): | ||
response = self.put(url, | ||
data=json.dumps(data), | ||
content_type="application/json", | ||
HTTP_ACCEPT="application/json", | ||
**extra) | ||
return self._load_json(response.content), response | ||
|
||
def rest_get(self, url, **data): | ||
response = self.get(url, | ||
data=data, | ||
HTTP_ACCEPT="application/json") | ||
return self._load_json(response.content), response | ||
|
||
def rest_delete(self, url): | ||
response = self.delete(url, | ||
HTTP_ACCEPT="application/json") | ||
return self._load_json(response.content), response |