Browse files

Small refactoring

  • Loading branch information...
1 parent a011cf2 commit 6485f29e05c4015d2f9142b3a143a7cbbb61cc07 @klen committed Aug 16, 2012
View
372 ChangeLog.txt
@@ -1,372 +0,0 @@
-CHANGES
-=======
-
-## 2012-07-17 1.7.0
--------------------
-* Added BSON support
-
-## 2012-07-16 1.6.0
--------------------
-* Upgrade 'adrest_include'
-
-## 2012-06-26 1.5.0
--------------------
-* Added manytomany field tests.
-
-## 2012-06-07 1.4.3
--------------------
-* Fixed RPC callbacks.
-
-## 2012-06-01 1.4.0
--------------------
-* Upgraded PUT and DELETE methods.
-* Support for many resources.
-
-## 2012-05-29 1.3.0
--------------------
-* Fixed parsing of resources
-
-## 2012-05-24 1.2.11
---------------------
-* API-map has been updated.
-* Fixed RPC headers.
-* Added JavaScript templates.
-* Added `adrest_jsonify` tag.
-
-## 2012-05-23 1.2.2
--------------------
-* Add JSONP emitters, add jsonp support to rpc
-
-## 2012-05-22 1.2.1
--------------------
-* Add simple JSON RPC
-
-## 2012-05-11 1.1.21
---------------------
-* Parse resources from POST and PUT
-* Fix pagination
-
-## 2012-04-28 1.1.20
---------------------
-* Fix accesskey admin
-
-## 2012-04-26 1.1.19
---------------------
-* Not resource checking on options request (ALLOW_OPTIONS)
-
-## 2012-04-09 1.1.17
---------------------
-* Add field label to map.
-
-## 2012-04-09 1.1.15
---------------------
-* Delete returned empty response.
-
-## 2012-04-06 1.1.14
---------------------
-* Add ordering to adrest models
-
-## 2012-04-03 1.1.12
---------------------
-* Minor fix of allow header
-
-## 2012-04-01 1.1.11
---------------------
-* Do not change data in request from forms
-
-## 2012-03-29 1.1.10
---------------------
-* Add ADREST_ACCESSKEY option
-* Fix PUT and PATH requests
-
-## 2012-03-19 1.1.7
--------------------
-* Allows fields query (field__startswith) in GET filters
-
-## 2012-03-07 1.1.6
--------------------
-* Authenticators refactoring
-
-## 2012-03-06 1.1.3
--------------------
-* More usefull api map
-
-## 2012-02-29 1.1.2
--------------------
-* Fix accesskey admin
-
-## 2012-02-28 1.1.0
--------------------
-* Add not string content for HttpError
-* Add TextEmitter
-* Add SerializedHttpResponse (HttpResponse now returned as is)
-* Add api owned signals
-
-## 2012-02-27 1.0.18
---------------------
-* More information in adrest signals.
-* Fix API urls
-
-## 2012-02-23 1.0.15
---------------------
-* Add 'api_prefix' option to API
-* Fix templates
-* Append http HEAD method support by default
-* New resource method: as_url
-* Resources now parse from URL and GET
-* get_resources_from_uri -> get_resources
-
-## 2012-02-17 1.0.6
--------------------
-* More accurate html (@hogart)
-* Append ADREST temlatetags (adrest_include)
-
-## 2012-02-13 1.0.4
--------------------
-* !!! No backward compatible (get_filter_options -> get_queryset)
-
-## 2012-02-12 1.0.3
--------------------
-* More information in mail about errors
-* Tests refactoring (@lispython)
-* Fixed json emmiter (@lispython)
-* Added pagination headers (@lispython)
-
-## 2012-01-30 1.0.2
--------------------
-* Minor release
-
-## 2012-01-30 1.0.1
--------------------
-* Add API errors email notifications
-
-## 2012-01-27 1.0.0
--------------------
-* Global refactoring
-* Fix access log
-
-## 2012-01-25 0.7.93
---------------------
-* Minor fix of api map
-* Set is now json serialized
-
-## 2011-12-23 0.7.92
---------------------
-* Model in resource maybe in string format
-
-## 2011-11-23 0.7.9
--------------------
-* Reverse uri in tests by resource name
-
-## 2011-11-14 0.7.7
--------------------
-* Fix settings and cross domain 'OPTIONS'
-
-## 2011-11-11 0.7.5
--------------------
-* Fix filter_options
-
-## 2011-11-05 0.7.4
--------------------
-* Fix precache queryset in handlers
-
-## 2011-11-05 0.7.2
--------------------
-* Minor fix
-
-## 2011-10-28 0.7.1
--------------------
-* Add version information to django access admin
-
-## 2011-10-27 0.7.0
--------------------
-* Add version to access log
- (Manual migration: ALTER TABLE adrest_access ADD COLUMN version varchar(25);)
-
-## 2011-10-26 0.6.62
---------------------
-* Fix throttle cache key length
-
-## 2011-10-13 0.6.5
--------------------
-* Fix prefix on partitial form
-
-## 2011-10-05 0.6.4
--------------------
-* Allow to create api without version
-
-## 2011-10-03 0.6.3
--------------------
-* Add django 1.3.1 support and some test utils
-
-## 2011-09-23 0.6.0
--------------------
-* Allow filter has many values from GET
-
-## 2011-09-23 0.5.97
---------------------
-* Fix partitial form
-
-## 2011-09-22 0.5.95
---------------------
-* Fix map for user auth
-
-## 2011-09-22 0.5.94
---------------------
-* Fix partitial form.
-
-## 2011-09-20 0.5.93
---------------------
-* Add html map
-
-## 2011-09-19 0.5.92
---------------------
-* Add fields to map
-* Fix check owner code (if child FK to parent is None -- it's, nobody owns this
-child, so everyone can get it)
-
-
-## 2011-09-01 0.5.3
--------------------
-* Extract check owners method
-
-
-## 2011-08-26 0.5.2
--------------------
-* Upgrade JSON emitter
-* Add XML emitter
-
-
-## 2011-08-24 0.4.7
--------------------
-* Add some tests
-
-
-## 2011-08-18 0.4.4
--------------------
-* Add some tests
-* Add map of api resources
-* Begin code refactoring
-
-
-## 2011-08-04 0.3.11
---------------------
-* Fix access key admin
-
-
-## 2011-07-22 0.3.1
--------------------
-* Fix access log bug
-
-
-## 2011-07-19 0.2.98
---------------------
-* Fix put method
-
-
-## 2011-07-18 0.2.97
---------------------
-* In OPTIONS method always used only JSONEmitter
-
-
-## 2011-06-16 0.2.96
---------------------
-* Allow disable authentication on OPTIONS http methods
-
-
-## 2011-06-15 0.2.95
---------------------
-* Add OPTIONS method
-
-
-## 2011-06-13 0.2.92
---------------------
-* Fix access for nested objects
-
-
-## 2011-05-27 0.2.9
--------------------
-* Fix DEBUG mode
-
-
-## 2011-05-23 0.2.7
--------------------
-* Fix statuses. https://github.com/klen/adrest/issues/4
-
-
-## 2011-05-03 0.2.6
--------------------
-* Fix handlers and forms
-
-
-## 2011-05-03 0.2.5
--------------------
-* Add form_exclude option to resource
-
-
-## 2011-04-27 0.2.4
--------------------
-* Some more frendly Access logs
-
-
-## 2011-04-25 0.2.3
--------------------
-* Fix accesslog truncate content
-* Improve access log admin
-
-
-## 2011-04-25 0.2.1
--------------------
-* Add `log` resource param
-* Truncate response content in log to 5000 symbols
-* Add throttle
-
-## 2011-04-22 0.1.9
--------------------
-* Add server timestamp to all request
-
-## 2011-04-21 0.1.8
--------------------
-* Minor fixes
-
-## 2011-04-18 0.1.5
--------------------
-* Fix empty content-type
-
-## 2011-04-18 0.1.4
--------------------
-* Add api_request_started and api_request_finished signals
-
-## 2011-04-17 0.1.3
--------------------
-* Add method field in access log model
-
-## 2011-04-15 0.1.2
--------------------
-* Fix tests fail for PUT requests
-
-## 2011-04-15 0.1.1
--------------------
-* Fix bug with empty request.data on PUT method when content-type is 'application/x-www-form-urlencoded'
-
-## 2011-04-12 0.1.0
--------------------
-* Fix invalid identifier in url
-* Add queryset parameter to handler class
-
-## 2011-04-07 0.0.8
--------------------
-* Add owner resource checks
-
-## 2011-04-07 0.0.7
--------------------
-* Fix url regex generate bug
-
-## 2011-04-04 0.0.6
--------------------
-* Many bugs fixed
-* Access logging work on
-
-## 2011-03-31 0.0.2
--------------------
-* First public release
View
369 Changelog
@@ -0,0 +1,369 @@
+2012-07-17 klen 1.7.0
+
+ * Added BSON support
+
+2012-07-16 klen 1.6.0
+
+ * Upgrade 'adrest_include'
+
+2012-06-26 klen 1.5.0
+
+ * Added manytomany field tests.
+
+2012-06-07 klen 1.4.3
+
+ * Fixed RPC callbacks.
+
+2012-06-01 klen 1.4.0
+
+ * Upgraded PUT and DELETE methods.
+ * Support for many resources.
+
+2012-05-29 klen 1.3.0
+
+ * Fixed parsing of resources
+
+2012-05-24 klen 1.2.11
+
+ * API-map has been updated.
+ * Fixed RPC headers.
+ * Added JavaScript templates.
+ * Added `adrest_jsonify` tag.
+
+2012-05-23 klen 1.2.2
+
+ * Add JSONP emitters, add jsonp support to rpc
+
+2012-05-22 1.2.1
+
+ * Add simple JSON RPC
+
+2012-05-11 1.1.21
+
+ * Parse resources from POST and PUT
+ * Fix pagination
+
+2012-04-28 1.1.20
+
+ * Fix accesskey admin
+
+2012-04-26 1.1.19
+
+ * Not resource checking on options request (ALLOW_OPTIONS)
+
+2012-04-09 1.1.17
+
+ * Add field label to map.
+
+2012-04-09 1.1.15
+
+ * Delete returned empty response.
+
+2012-04-06 1.1.14
+
+ * Add ordering to adrest models
+
+2012-04-03 1.1.12
+
+ * Minor fix of allow header
+
+2012-04-01 1.1.11
+
+ * Do not change data in request from forms
+
+2012-03-29 1.1.10
+
+ * Add ADREST_ACCESSKEY option
+ * Fix PUT and PATH requests
+
+2012-03-19 1.1.7
+
+ * Allows fields query (field__startswith) in GET filters
+
+2012-03-07 1.1.6
+
+ * Authenticators refactoring
+
+2012-03-06 1.1.3
+
+ * More usefull api map
+
+2012-02-29 1.1.2
+
+ * Fix accesskey admin
+
+2012-02-28 1.1.0
+
+ * Add not string content for HttpError
+ * Add TextEmitter
+ * Add SerializedHttpResponse (HttpResponse now returned as is)
+ * Add api owned signals
+
+2012-02-27 1.0.18
+
+ * More information in adrest signals.
+ * Fix API urls
+
+2012-02-23 1.0.15
+
+ * Add 'api_prefix' option to API
+ * Fix templates
+ * Append http HEAD method support by default
+ * New resource method: as_url
+ * Resources now parse from URL and GET
+ * get_resources_from_uri -> get_resources
+
+2012-02-17 1.0.6
+
+ * More accurate html (@hogart)
+ * Append ADREST temlatetags (adrest_include)
+
+2012-02-13 1.0.4
+
+ * !!! No backward compatible (get_filter_options -> get_queryset)
+
+2012-02-12 1.0.3
+
+ * More information in mail about errors
+ * Tests refactoring (@lispython)
+ * Fixed json emmiter (@lispython)
+ * Added pagination headers (@lispython)
+
+2012-01-30 1.0.2
+
+ * Minor release
+
+2012-01-30 1.0.1
+
+ * Add API errors email notifications
+
+2012-01-27 1.0.0
+
+ * Global refactoring
+ * Fix access log
+
+2012-01-25 0.7.93
+
+ * Minor fix of api map
+ * Set is now json serialized
+
+2011-12-23 0.7.92
+
+ * Model in resource maybe in string format
+
+2011-11-23 0.7.9
+
+ * Reverse uri in tests by resource name
+
+2011-11-14 0.7.7
+
+ * Fix settings and cross domain 'OPTIONS'
+
+2011-11-11 0.7.5
+
+ * Fix filter_options
+
+2011-11-05 0.7.4
+
+ * Fix precache queryset in handlers
+
+2011-11-05 0.7.2
+
+ * Minor fix
+
+2011-10-28 0.7.1
+
+ * Add version information to django access admin
+
+2011-10-27 0.7.0
+
+ * Add version to access log
+ (Manual migration: ALTER TABLE adrest_access ADD COLUMN version varchar(25);)
+
+2011-10-26 0.6.62
+
+ * Fix throttle cache key length
+
+2011-10-13 0.6.5
+
+ * Fix prefix on partitial form
+
+2011-10-05 0.6.4
+
+ * Allow to create api without version
+
+2011-10-03 0.6.3
+
+ * Add django 1.3.1 support and some test utils
+
+2011-09-23 0.6.0
+
+ * Allow filter has many values from GET
+
+2011-09-23 0.5.97
+
+ * Fix partitial form
+
+2011-09-22 0.5.95
+
+ * Fix map for user auth
+
+2011-09-22 0.5.94
+
+ * Fix partitial form.
+
+2011-09-20 0.5.93
+
+ * Add html map
+
+2011-09-19 0.5.92
+
+ * Add fields to map
+ * Fix check owner code (if child FK to parent is None -- it's, nobody owns this
+ child, so everyone can get it)
+
+
+2011-09-01 0.5.3
+
+ * Extract check owners method
+
+
+2011-08-26 0.5.2
+
+ * Upgrade JSON emitter
+ * Add XML emitter
+
+
+2011-08-24 0.4.7
+
+ * Add some tests
+
+
+2011-08-18 0.4.4
+
+ * Add some tests
+ * Add map of api resources
+ * Begin code refactoring
+
+
+2011-08-04 0.3.11
+
+ * Fix access key admin
+
+
+2011-07-22 0.3.1
+
+ * Fix access log bug
+
+
+2011-07-19 0.2.98
+
+ * Fix put method
+
+
+2011-07-18 0.2.97
+
+ * In OPTIONS method always used only JSONEmitter
+
+
+2011-06-16 0.2.96
+
+ * Allow disable authentication on OPTIONS http methods
+
+
+2011-06-15 0.2.95
+
+ * Add OPTIONS method
+
+
+2011-06-13 0.2.92
+
+ * Fix access for nested objects
+
+
+2011-05-27 0.2.9
+
+ * Fix DEBUG mode
+
+
+2011-05-23 0.2.7
+
+ * Fix statuses. https://github.com/klen/adrest/issues/4
+
+
+2011-05-03 0.2.6
+
+ * Fix handlers and forms
+
+
+2011-05-03 0.2.5
+
+ * Add form_exclude option to resource
+
+
+2011-04-27 0.2.4
+
+ * Some more frendly Access logs
+
+
+2011-04-25 0.2.3
+
+ * Fix accesslog truncate content
+ * Improve access log admin
+
+
+2011-04-25 0.2.1
+
+ * Add `log` resource param
+ * Truncate response content in log to 5000 symbols
+ * Add throttle
+
+2011-04-22 0.1.9
+
+ * Add server timestamp to all request
+
+2011-04-21 0.1.8
+
+ * Minor fixes
+
+2011-04-18 0.1.5
+
+ * Fix empty content-type
+
+2011-04-18 0.1.4
+
+ * Add api_request_started and api_request_finished signals
+
+2011-04-17 0.1.3
+
+ * Add method field in access log model
+
+2011-04-15 0.1.2
+
+ * Fix tests fail for PUT requests
+
+2011-04-15 0.1.1
+
+ * Fix bug with empty request.data on PUT method when content-type is 'application/x-www-form-urlencoded'
+
+2011-04-12 0.1.0
+
+ * Fix invalid identifier in url
+ * Add queryset parameter to handler class
+
+2011-04-07 0.0.8
+
+ * Add owner resource checks
+
+2011-04-07 0.0.7
+
+ * Fix url regex generate bug
+
+2011-04-04 0.0.6
+
+ * Many bugs fixed
+ * Access logging work on
+
+2011-03-31 0.0.2
+
+ * First public release
View
2 DESCRIPTION
@@ -1 +1 @@
-Adrest - another django REST. Simple application for quick build RESTfull API.
+Adrest - Another Django REST. Simple application for quick build REST API.
View
1 README
@@ -1 +0,0 @@
-README.rst
View
18 README.rst
@@ -9,20 +9,38 @@ Documentation in construction.
:target: http://travis-ci.org/klen/adrest
:alt: Build Status
+Examples: ::
+
+ from adrest.api import Api
+ from adrest.views import ResourceView
+
+ class BookResource(ResourceView):
+ allowed_methods = 'get', 'post'
+ model = 'books.book'
+
+ api = Api(version(1, 0, 0))
+ api.register(BookResource)
+
+ urlpatterns = api.urls
+
+
+
Requirements
=============
- python >= 2.6
- django >= 1.4.0
+
Installation
=============
**Adrest** should be installed using pip: ::
pip install adrest
+
Setup
=====
View
8 adrest/map.py
@@ -38,14 +38,16 @@ def gen_apimap(self):
required=f.required and f.initial is None,
label=f.label,
help=smart_unicode(f.help_text + ''))
- )
+ )
for name, f in resource.form.base_fields.iteritems()
if not (isinstance(f, ModelChoiceField) and f.choices.queryset.model in models)
]
for a in resource.authenticators:
info['fields'] += a.get_fields()
- info['auth'] = set(a.__doc__ or 'Custom' for a in resource.authenticators)
- key = resource.meta.url_regex.replace("(?P", "").replace("[^/]+)", "").replace("?:", "").replace("$", "")
+ info['auth'] = set(
+ a.__doc__ or 'Custom' for a in resource.authenticators)
+ key = resource.meta.url_regex.replace("(?P", "").replace(
+ "[^/]+)", "").replace("?:", "").replace("$", "")
yield key, info
View
12 adrest/mixin/auth.py
@@ -1,8 +1,8 @@
-from adrest.utils import status
-from adrest import settings
-from adrest.utils.auth import AnonimousAuthenticator, BaseAuthenticator
-from adrest.utils.exceptions import HttpError
-from adrest.utils.tools import as_tuple
+from ..settings import ALLOW_OPTIONS
+from ..utils import status
+from ..utils.auth import AnonimousAuthenticator, BaseAuthenticator
+from ..utils.exceptions import HttpError
+from ..utils.tools import as_tuple
def check_authenticators(authenticators):
@@ -35,7 +35,7 @@ def authenticate(self, request):
"""
authenticators = self.authenticators
- if request.method == 'OPTIONS' and settings.ALLOW_OPTIONS:
+ if request.method == 'OPTIONS' and ALLOW_OPTIONS:
authenticators = AnonimousAuthenticator,
for authenticator in authenticators:
View
8 adrest/mixin/emitter.py
@@ -1,10 +1,10 @@
import mimeparse
from django.http import HttpResponse
-from adrest.utils import MetaOptions
-from adrest.utils.emitter import JSONEmitter, BaseEmitter
-from adrest.utils.tools import as_tuple
-from adrest.utils.paginator import Paginator
+from ..utils import MetaOptions
+from ..utils.emitter import JSONEmitter, BaseEmitter
+from ..utils.paginator import Paginator
+from ..utils.tools import as_tuple
class EmitterMeta(type):
View
33 adrest/mixin/handler.py
@@ -6,12 +6,12 @@
from django.db.models.sql.constants import LOOKUP_SEP
from django.http import HttpResponse
-from adrest.forms import PartitialForm
-from adrest.settings import LIMIT_PER_PAGE
-from adrest.utils import status, MetaOptions, UpdatedList
-from adrest.utils.exceptions import HttpError
-from adrest.utils.paginator import Paginator
-from adrest.utils.tools import as_tuple
+from ..forms import PartitialForm
+from ..settings import LIMIT_PER_PAGE
+from ..utils import status, MetaOptions, UpdatedList
+from ..utils.exceptions import HttpError
+from ..utils.paginator import Paginator
+from ..utils.tools import as_tuple
logger = getLogger('django.request')
@@ -26,8 +26,8 @@ def __new__(mcs, name, bases, params):
# Create model from string
if isinstance(cls.model, basestring):
assert '.' in cls.model, ("'model_class' must be either a model"
- " or a model name in the format"
- " app_label.model_name")
+ " or a model name in the format"
+ " app_label.model_name")
cls.model = get_model(*cls.model.split("."))
if cls.model:
@@ -86,7 +86,8 @@ def post(self, request, **resources):
form = self.form(data=deepcopy(request.data), **resources)
if form.is_valid():
return form.save()
- raise HttpError(form.errors.as_text(), status=status.HTTP_400_BAD_REQUEST)
+ raise HttpError(
+ form.errors.as_text(), status=status.HTTP_400_BAD_REQUEST)
def put(self, request, **resources):
content = resources.get(self.meta.name)
@@ -95,9 +96,11 @@ def put(self, request, **resources):
updated = UpdatedList()
for o in as_tuple(content):
- form = self.form(data=deepcopy(request.data), instance=o, **resources)
+ form = self.form(
+ data=deepcopy(request.data), instance=o, **resources)
if not form.is_valid():
- raise HttpError(form.errors.as_text(), status=status.HTTP_400_BAD_REQUEST)
+ raise HttpError(
+ form.errors.as_text(), status=status.HTTP_400_BAD_REQUEST)
updated.append(form.save())
return updated if isinstance(content, list) else updated[-1]
@@ -125,7 +128,8 @@ def get_queryset(self, request, **resources):
return None
# Make filters from URL variables or resources
- filters = dict((k, v) for k, v in resources.iteritems() if k in self.meta.model_fields)
+ filters = dict((k, v) for k, v in resources.iteritems(
+ ) if k in self.meta.model_fields)
qs = self.queryset.filter(**filters)
@@ -137,7 +141,8 @@ def get_queryset(self, request, **resources):
if not field_name in self.meta.model_fields or field_name in filters:
continue
- converter = self.model._meta.get_field(field).to_python if len(tokens) == 1 else lambda v: v
+ converter = self.model._meta.get_field(
+ field).to_python if len(tokens) == 1 else lambda v: v
value = map(converter, request.GET.getlist(field))
if len(value) > 1:
@@ -156,3 +161,5 @@ def paginate(self, request, qs):
""" Paginate queryset.
"""
return Paginator(request, qs, self.limit_per_page)
+
+# pymode:lint_ignore=E1102
View
6 adrest/mixin/parser.py
@@ -1,6 +1,6 @@
-from adrest.utils.parser import FormParser, XMLParser, JSONParser, BaseParser
-from adrest.utils import MetaOptions
-from adrest.utils.tools import as_tuple
+from ..utils import MetaOptions
+from ..utils.parser import FormParser, XMLParser, JSONParser, BaseParser
+from ..utils.tools import as_tuple
class ParserMeta(type):
View
6 adrest/mixin/throttle.py
@@ -1,6 +1,6 @@
-from adrest.utils import status
-from adrest.utils.exceptions import HttpError
-from adrest.utils.throttle import BaseThrottle
+from ..utils import status
+from ..utils.exceptions import HttpError
+from ..utils.throttle import BaseThrottle
class ThrottleMeta(type):
View
3 adrest/rpc.py
@@ -57,3 +57,6 @@ def get_name(self):
if self.target_resource:
return self.target_resource.meta.name
return self.meta.name
+
+
+# pymode:lint_ignore=E1103
View
2 adrest/settings.py
@@ -1,7 +1,7 @@
" Adrest API settings. "
from django.conf import settings
-from adrest.utils.tools import as_tuple
+from .utils.tools import as_tuple
# Enable Adrest API logs
View
6 adrest/tests/__init__.py
@@ -1 +1,5 @@
-" adrest.tests "
+" Adrest test utils. "
+
+from .utils import AdrestClient, AdrestTestCase
+
+assert AdrestClient and AdrestTestCase
View
3 adrest/tests/utils.py
@@ -13,9 +13,10 @@
class AdrestClient(Client):
- def patch(self, path, data={}, content_type=MULTIPART_CONTENT, follow=False, **extra):
+ def patch(self, path, data=None, content_type=MULTIPART_CONTENT, follow=False, **extra):
" Send a resource to the server using PATCH. "
+ data = data or dict()
patch_data = self._encode_data(data, content_type)
parsed = urlparse(path)
r = {
View
8 adrest/utils/auth.py
@@ -3,7 +3,7 @@
from django.contrib.auth import authenticate
from django.middleware.csrf import CsrfViewMiddleware
-from adrest import models
+from ..models import AccessKey
class BaseAuthenticator(object):
@@ -44,7 +44,7 @@ def __init__(self, resource=None):
super(_UserAuthenticator, self).__init__(resource)
self.user = None
- def get_identifier(self, request):
+ def get_identifier(self, request=None):
if self.user and self.user.is_active:
self.identifier = self.user.username
return self.identifier
@@ -107,11 +107,11 @@ def authenticate(self, request=None):
"""
try:
access_key = request.META.get('HTTP_AUTHORIZATION') or request.REQUEST['key']
- api_key = models.AccessKey.objects.get(key=access_key)
+ api_key = AccessKey.objects.get(key=access_key)
self.user = request.user = api_key.user
return self.get_identifier(request)
- except(KeyError, models.AccessKey.DoesNotExist):
+ except(KeyError, AccessKey.DoesNotExist):
return False
return False
View
6 adrest/utils/emitter.py
@@ -6,11 +6,11 @@
from django.http import HttpResponse
from django.template import RequestContext, loader
+from ..utils import UpdatedList
from .paginator import Paginator
+from .response import SerializedHttpResponse
from .serializer import json_dumps, xml_dumps
-from adrest.utils import UpdatedList
-from adrest.utils.status import HTTP_200_OK
-from adrest.utils.response import SerializedHttpResponse
+from .status import HTTP_200_OK
class EmitterMeta(type):
View
4 adrest/utils/paginator.py
@@ -2,8 +2,8 @@
from django.core.paginator import InvalidPage, Paginator as DjangoPaginator
-from . import status as http_status
from .exceptions import HttpError
+from .status import HTTP_400_BAD_REQUEST
class Paginator(object):
@@ -17,7 +17,7 @@ def __init__(self, request, qs, max_res):
try:
self.page = self.paginator.page(page_num)
except InvalidPage:
- raise HttpError("Invalid page", status=http_status.HTTP_400_BAD_REQUEST)
+ raise HttpError("Invalid page", status=HTTP_400_BAD_REQUEST)
@property
def count(self):
View
6 adrest/utils/parser.py
@@ -1,7 +1,7 @@
from django.utils import simplejson as json
-from . import status
from .exceptions import HttpError
+from .status import HTTP_400_BAD_REQUEST
class BaseParser(object):
@@ -39,7 +39,7 @@ def parse(request):
try:
return json.loads(request.raw_post_data)
except ValueError, e:
- raise HttpError('JSON parse error - %s' % str(e), status=status.HTTP_400_BAD_REQUEST)
+ raise HttpError('JSON parse error - %s' % str(e), status=HTTP_400_BAD_REQUEST)
class XMLParser(BaseParser):
@@ -63,7 +63,7 @@ def parse(request):
try:
return BSON(request.raw_post_data).decode()
except ValueError, e:
- raise HttpError('BSON parse error - %s' % str(e), status=status.HTTP_400_BAD_REQUEST)
+ raise HttpError('BSON parse error - %s' % str(e), status=HTTP_400_BAD_REQUEST)
except ImportError:
pass
View
2 adrest/utils/throttle.py
@@ -3,7 +3,7 @@
from django.core.cache import cache
-from adrest.settings import THROTTLE_AT, THROTTLE_TIMEFRAME
+from ..settings import THROTTLE_AT, THROTTLE_TIMEFRAME
class BaseThrottle(object):
View
2 adrest/utils/tools.py
@@ -31,7 +31,7 @@ def gen_url_regex(resource):
yield r.url_regex.rstrip('/$').lstrip('^')
else:
yield '%(name)s/(?P<%(name)s>[^/]+)' % dict(
- name=r.meta.name)
+ name=r.meta.name)
for p in resource.url_params:
yield '%(name)s/(?P<%(name)s>[^/]+)' % dict(name=p)
View
86 adrest/views.py
@@ -11,19 +11,20 @@
from django.views.decorators.csrf import csrf_exempt
from django.views.generic import View
+from .mixin import auth, emitter, handler, parser, throttle
+from .settings import ALLOW_OPTIONS, DEBUG, MAIL_ERRORS
+from .signals import api_request_started, api_request_finished
from .utils import status, MetaOptions
from .utils.exceptions import HttpError
-from .utils.tools import as_tuple, gen_url_name, gen_url_regex, fix_request
from .utils.response import SerializedHttpResponse
-from adrest import settings
-from adrest.mixin import auth, emitter, handler, parser, throttle
-from adrest.signals import api_request_started, api_request_finished
+from .utils.tools import as_tuple, gen_url_name, gen_url_regex, fix_request
logger = getLogger('django.request')
-class ResourceMetaClass(handler.HandlerMeta, throttle.ThrottleMeta, emitter.EmitterMeta,
+class ResourceMetaClass(
+ handler.HandlerMeta, throttle.ThrottleMeta, emitter.EmitterMeta,
parser.ParserMeta, auth.AuthMeta):
""" MetaClass for ResourceView.
Create meta options.
@@ -45,10 +46,12 @@ def __new__(mcs, name, bases, params):
try:
cls.meta.parents += cls.parent.meta.parents + [cls.parent]
except AttributeError:
- raise TypeError("%s.parent must be instance of %s" % (name, "ResourceView"))
+ raise TypeError("%s.parent must be instance of %s" %
+ (name, "ResourceView"))
# Meta name (maybe precalculate in handler)
- cls.meta.name = cls.meta.name or cls.name or ''.join(bit for bit in name.split('Resource') if bit).lower()
+ cls.meta.name = cls.meta.name or cls.name or ''.join(
+ bit for bit in name.split('Resource') if bit).lower()
# Prepare urls
cls.url_params = list(as_tuple(cls.url_params))
@@ -61,9 +64,9 @@ def __new__(mcs, name, bases, params):
def prepare_methods(methods):
" Prepare allowed methods. "
- methods = as_tuple(methods)
+ methods = tuple([str(m).upper() for m in as_tuple(methods)])
- if not 'OPTIONS' in methods and settings.ALLOW_OPTIONS:
+ if not 'OPTIONS' in methods and ALLOW_OPTIONS:
methods += 'OPTIONS',
if not 'HEAD' in methods and 'GET' in methods:
@@ -73,11 +76,11 @@ def prepare_methods(methods):
class ResourceView(handler.HandlerMixin,
- throttle.ThrottleMixin,
- emitter.EmitterMixin,
- parser.ParserMixin,
- auth.AuthMixin,
- View):
+ throttle.ThrottleMixin,
+ emitter.EmitterMixin,
+ parser.ParserMixin,
+ auth.AuthMixin,
+ View):
# Create meta options
__metaclass__ = ResourceMetaClass
@@ -136,10 +139,11 @@ def dispatch(self, request, _emit_=True, **resources):
# Throttle check
self.throttle_check()
- if request.method != 'OPTIONS' or not settings.ALLOW_OPTIONS:
+ if request.method != 'OPTIONS' or not ALLOW_OPTIONS:
# Get required resources
- resources = self.get_resources(request, resource=self, **resources)
+ resources = self.get_resources(
+ request, resource=self, **resources)
# Check owners
self.check_owners(**resources)
@@ -164,10 +168,12 @@ def dispatch(self, request, _emit_=True, **resources):
except HttpError, e:
response = SerializedHttpResponse(e.content, status=e.status)
if _emit_:
- response = self.emit(response, request=request, emitter=e.emitter)
+ response = self.emit(
+ response, request=request, emitter=e.emitter)
except (AssertionError, ValidationError), e:
- response = SerializedHttpResponse(unicode(e), status=status.HTTP_400_BAD_REQUEST)
+ response = SerializedHttpResponse(
+ unicode(e), status=status.HTTP_400_BAD_REQUEST)
if _emit_:
response = self.emit(response, request=request)
@@ -178,10 +184,12 @@ def dispatch(self, request, _emit_=True, **resources):
errors_mail(response, request)
# Send finished signal
- api_request_finished.send(self, request=request, response=response, **resources)
+ api_request_finished.send(
+ self, request=request, response=response, **resources)
# Send finished signal in API context
- self.api and self.api.request_finished.send(self, request=request, response=response, **resources)
+ if self.api:
+ self.api.request_finished.send(self, request=request, response=response, **resources)
return response
@@ -191,20 +199,23 @@ def check_method_allowed(cls, method):
"""
if not method in cls.callmap.keys():
raise HttpError('Unknown or unsupported method \'%s\'' % method,
- status=status.HTTP_501_NOT_IMPLEMENTED)
+ status=status.HTTP_501_NOT_IMPLEMENTED)
if not method in cls.allowed_methods:
- raise HttpError('Method \'%s\' not allowed on this resource.' % method,
- status=status.HTTP_405_METHOD_NOT_ALLOWED)
+ raise HttpError(
+ 'Method \'%s\' not allowed on this resource.' % method,
+ status=status.HTTP_405_METHOD_NOT_ALLOWED)
@classmethod
def get_resources(cls, request, resource=None, **resources):
" Parse resource objects from URL and GET. "
if cls.parent:
- resources = cls.parent.get_resources(request, resource=resource, **resources)
+ resources = cls.parent.get_resources(
+ request, resource=resource, **resources)
- pks = resources.get(cls.meta.name) or request.REQUEST.getlist(cls.meta.name)
+ pks = resources.get(
+ cls.meta.name) or request.REQUEST.getlist(cls.meta.name)
if not cls.model or not pks:
return resources
@@ -216,15 +227,16 @@ def get_resources(cls, request, resource=None, **resources):
else:
assert cls.queryset.filter(pk__in=pks).count()
- resources[cls.meta.name] = list(cls.queryset.filter(pk__in=pks))
+ resources[cls.meta.name] = list(
+ cls.queryset.filter(pk__in=pks))
except (ObjectDoesNotExist, ValueError, AssertionError):
raise HttpError("Resource not found.",
- status=status.HTTP_404_NOT_FOUND)
+ status=status.HTTP_404_NOT_FOUND)
except MultipleObjectsReturned:
raise HttpError("Resources conflict.",
- status=status.HTTP_409_CONFLICT)
+ status=status.HTTP_409_CONFLICT)
return resources
@@ -248,18 +260,20 @@ def check_owners(cls, **resources):
if cls.model and cls.parent.model and objects:
try:
pr = resources.get(cls.parent.meta.name)
- assert pr and all(pr.pk == getattr(o, "%s_id" % cls.parent.meta.name, None) for o in objects)
+ assert pr and all(pr.pk == getattr(
+ o, "%s_id" % cls.parent.meta.name, None) for o in objects)
except AssertionError:
# 403 Error if there is error in parent-children relationship
- raise HttpError("Access forbidden.", status=status.HTTP_403_FORBIDDEN)
+ raise HttpError(
+ "Access forbidden.", status=status.HTTP_403_FORBIDDEN)
return True
@staticmethod
def handle_exception(e, request=None):
""" Handle code exception.
"""
- if settings.DEBUG:
+ if DEBUG:
raise
logger.exception('\nADREST API Error: %s' % request.path)
@@ -276,7 +290,8 @@ def as_url(cls, api=None, name_prefix='', url_prefix=''):
url_prefix = url_prefix and "%s/" % url_prefix
name_prefix = name_prefix and "%s-" % name_prefix
- url_regex = '^%s%s/?$' % (url_prefix, cls.meta.url_regex.lstrip('^').rstrip('/$'))
+ url_regex = '^%s%s/?$' % (
+ url_prefix, cls.meta.url_regex.lstrip('^').rstrip('/$'))
url_regex = url_regex.replace('//', '/')
url_name = '%s%s' % (name_prefix, cls.meta.url_name)
@@ -288,10 +303,11 @@ def get_name(self):
def errors_mail(response, request):
- if not response.status_code in settings.MAIL_ERRORS:
+ if not response.status_code in MAIL_ERRORS:
return False
- subject = 'ADREST API Error (%s): %s' % (response.status_code, request.path)
+ subject = 'ADREST API Error (%s): %s' % (
+ response.status_code, request.path)
stack_trace = '\n'.join(traceback.format_exception(*sys.exc_info()))
message = """
Stacktrace:
@@ -308,3 +324,5 @@ def errors_mail(response, request):
""" % (stack_trace, repr(getattr(request, 'data', None)), repr(request))
return mail_admins(subject, message, fail_silently=True)
+
+# pymode:lint_ignore=E1120
View
2 tests/main/resources.py
@@ -11,7 +11,7 @@ class AuthorResource(ResourceView):
class BookResource(ResourceView):
- allowed_methods = 'GET', 'POST', 'PUT', 'DELETE'
+ allowed_methods = 'GET', 'post', 'pUt', 'DELETE'
model = 'main.book'
parent = AuthorResource
View
2 todo.txt
@@ -1,2 +0,0 @@
-Add serializers: bplist, yaml
-Add patch method

0 comments on commit 6485f29

Please sign in to comment.