Permalink
Browse files

introducting root endpoint

  • Loading branch information...
1 parent 5386ed2 commit a7500ca99aa8354a406be5a90a7986190573fe52 @zbyte64 committed Jan 13, 2013
View
@@ -1,10 +1,12 @@
TODOs
=====
-links to communicate mimetype, media types to be aware and render things like img tags
+[done] links to communicate mimetype, media types to be aware and render things like img tags
OPTIONS to serialize through media type
CBVs that are clients, possible builtin site reosurce
-DirectoryResource -> generic resource browser (is a resource itself) - replace/refactor SiteResource and ApplicationResource
+[done] DirectoryResource -> generic resource browser (is a resource itself) - replace/refactor SiteResource and ApplicationResource
+
+RootEndpoint (aka resource site) for single endpoint or collection of endpoints
@@ -27,14 +27,18 @@ def __init__(self, site, path, url_args, url_kwargs):
def META(self):
return self.session_state['meta']
+ @property
+ def media_types(self):
+ return self.get_site().media_types
+
def get_response_type(self):
"""
Returns the active response type to be used
:rtype: string
"""
val = self.META.get('HTTP_ACCEPT', '')
- media_types = self.site.media_types.keys()
+ media_types = self.media_types.keys()
if not media_types:
return val
return mimeparse.best_match(media_types, val) or val
@@ -46,7 +50,7 @@ def get_request_type(self):
:rtype: string
"""
val = self.META.get('CONTENT_TYPE', self.META.get('HTTP_ACCEPT', ''))
- media_types = self.site.media_types.keys()
+ media_types = self.media_types.keys()
if not media_types:
return val
return mimeparse.best_match(media_types, val) or val
@@ -59,9 +63,9 @@ def get_request_media_type(self):
:rtype: string
"""
content_type = self.get_request_type()
- media_type_cls = self.site.media_types.get(content_type, None)
+ media_type_cls = self.media_types.get(content_type, None)
if media_type_cls is None:
- raise ValueError('Unrecognized request content type "%s". Choices are: %s' % (content_type, self.site.media_types.keys()))
+ raise ValueError('Unrecognized request content type "%s". Choices are: %s' % (content_type, self.media_types.keys()))
return media_type_cls(self)
def get_response_media_type(self):
@@ -72,9 +76,9 @@ def get_response_media_type(self):
:rtype: string
"""
content_type = self.get_response_type()
- media_type_cls = self.site.media_types.get(content_type, None)
+ media_type_cls = self.media_types.get(content_type, None)
if media_type_cls is None:
- raise ValueError('Unrecognized request content type "%s". Choices are: %s' % (content_type, self.site.media_types.keys()))
+ raise ValueError('Unrecognized request content type "%s". Choices are: %s' % (content_type, self.media_types.keys()))
return media_type_cls(self)
def get_resource(self, urlname):
@@ -169,7 +173,10 @@ def generate_response(self, link, state):
"""
media_type = self.get_response_media_type()
response_type = self.get_response_type()
- return state.generate_response(media_type=media_type, response_type=response_type, link=link)
+ return media_type.serialize(request=self, content_type=response_type, link=link, state=state)
+
+ def reverse(self, name, *args, **kwargs):
+ return self.get_site().reverse(name, *args, **kwargs)
class InternalAPIRequest(APIRequest):
"""
@@ -1,18 +1,37 @@
-from copy import copy
-
-from django.views.generic import View
-from django.conf.urls import patterns
-
from hyperadmin.clients.common import Client
+from hyperadmin.apirequests import HTTPAPIRequest
+from hyperadmin.endpoints import RootEndpoint
+
+class MediaTypeClientHTTPAPIRequest(HTTPAPIRequest):
+ def get_site(self):
+ """
+ Returns the bound site
+
+ :rtype: SiteResource
+ """
+ if 'site' not in self.endpoint_state:
+ bound_site = self.site.fork(api_request=self)
+ self.endpoint_state['site'] = bound_site
+ bound_site.post_register()
+ return self.endpoint_state['site']
-class EndpointProxy(View):
- endpoint = None
- endpoint_kwargs = {}
+class MediaTypeRootEndpoint(RootEndpoint):
+ apirequest_class = MediaTypeClientHTTPAPIRequest
+ inner_api_endpoint = None
+ client = None
+
+ def __init__(self, **kwargs):
+ super(MediaTypeRootEndpoint, self).__init__(**kwargs)
+ self.media_types = self.client.get_media_types()
+
+ def get_inner_api_endpoint(self):
+ if not hasattr(self, 'bound_inner_api_endpoint'):
+ self.bound_inner_api_endpoint = self.inner_api_endpoint.fork(create_apirequest=self.create_apirequest)
+ return self.bound_inner_api_endpoint
- def dispatch(self, request, *args, **kwargs):
- view = self.endpoint.get_view(**self.endpoint_kwargs)
- return view(request, *args, **kwargs)
+ def get_urls(self):
+ return self.get_inner_api_endpoint().get_urls()
class MediaTypeClient(Client):
'''
@@ -22,6 +41,7 @@ class MediaTypeClient(Client):
def __init__(self, api_endpoint, name='hyper-client', app_name='client'):
super(MediaTypeClient, self).__init__(api_endpoint, name=name, app_name=app_name)
+ self.endpoint = MediaTypeRootEndpoint(client=self, inner_api_endpoint=api_endpoint, name=name, app_name=app_name)
def get_media_types(self):
media_types = dict(self.api_endpoint.media_types)
@@ -32,33 +52,8 @@ def get_media_types(self):
def get_urls(self):
try:
- return self.traverse(self.api_endpoint.get_urls())
+ return self.endpoint.get_urls()
except Exception as error:
print error
raise
-
- def get_endpoint_kwargs(self):
- return {
- 'global_state': {
- 'site': self,
- }
- }
-
- #TODO find a better name
- def traverse(self, urlpatterns):
- new_patterns = list()
- for entry in urlpatterns:
- entry = copy(entry)
- if hasattr(entry, '_callback') and hasattr(entry._callback, 'endpoint'):
- endpoint = entry._callback.endpoint
- entry._callback = EndpointProxy.as_view(endpoint=endpoint, endpoint_kwargs=self.get_endpoint_kwargs())
- entry._callback.endpoint = endpoint
- elif hasattr(entry, 'url_patterns'):
- entry._urlconf_module = self.traverse(entry.url_patterns)
- new_patterns.append(entry)
- return patterns('', *new_patterns)
-
- def generate_response(self, media_type, content_type, link, state):
- api_request = state.endpoint.api_request
- media_type = self.get_media_types().get(content_type, media_type)(api_request=api_request)
- return media_type.serialize(request=api_request.request, content_type=content_type, link=link, state=state)
+
@@ -1,7 +1,9 @@
-from django.conf.urls.defaults import url
+from django.conf.urls.defaults import url, patterns
+from django.core.urlresolvers import reverse
from django.views.generic import View
from hyperadmin.links import Link, LinkCollection, LinkCollectorMixin
+from hyperadmin.apirequests import HTTPAPIRequest
from hyperadmin.hyperobjects import Item
from hyperadmin.states import EndpointState
from hyperadmin.views import EndpointViewMixin
@@ -97,6 +99,7 @@ def get_state_data(self):
data = {'endpoint_class':self.endpoint_class,
'endpoint_classes':self.get_endpoint_classes(),
'params':self.api_request.params,}
+ #TODO send params only if the api request was for this endpoint
return data
def get_state_kwargs(self):
@@ -128,7 +131,7 @@ def reverse(self, *args, **kwargs):
:rtype: string
"""
- return self.state.reverse(*args, **kwargs)
+ return self.api_request.reverse(*args, **kwargs)
#urls
@@ -246,12 +249,6 @@ def get_form_kwargs(self, item=None, **kwargs):
kwargs.setdefault('instance', item.instance)
return kwargs
- def get_view_kwargs(self):
- """
- :rtype: dict
- """
- return {}
-
def get_namespaces(self):
"""
:rtype: dictionary of namespaces
@@ -302,12 +299,66 @@ def get_prompt(self):
"""
return unicode(self)
+ #TODO deprecate this, replace with api_request.api_permission_check()
def api_permission_check(self, api_request):
return self.site.api_permission_check(api_request)
def generate_response(self, link):
return self.api_request.generate_response(link=link, state=self.state)
+class RootEndpoint(BaseEndpoint):
+ namespace = None
+ media_types = None
+ apirequest_class = HTTPAPIRequest
+
+ def __init__(self, **kwargs):
+ kwargs.setdefault('media_types', dict())
+ kwargs.setdefault('namespace', str(id(self)))
+ super(RootEndpoint, self).__init__(**kwargs)
+
+ def get_site(self):
+ if self.api_request:
+ return self.api_request.get_site()
+ return self
+
+ site = property(get_site)
+
+ def get_urls(self):
+ #TODO this goes into standalone endpoint...
+ urlpatterns = self.get_extra_urls()
+ urlpatterns += patterns('', self.get_url_object())
+ return urlpatterns
+
+ @property
+ def urlpatterns(self):
+ return self.get_urls()
+
+ def get_extra_urls(self):
+ return patterns('',)
+
+ def urls(self):
+ return self, None, self.namespace
+ urls = property(urls)
+
+ def reverse(self, name, *args, **kwargs):
+ return reverse('%s:%s' % (self.namespace, name), args=args, kwargs=kwargs)
+
+ def register_media_type(self, media_type, media_type_handler):
+ self.media_types[media_type] = media_type_handler
+
+ def get_api_request_kwargs(self, **kwargs):
+ params = {'site':self}
+ params.update(kwargs)
+ return params
+
+ def create_apirequest(self, request, url_args, url_kwargs):
+ kwargs = self.get_api_request_kwargs(request=request, url_args=url_args, url_kwargs=url_kwargs)
+ api_request = self.apirequest_class(**kwargs)
+ api_request.populate_session_data_from_request(request)
+ if self.global_state is not None:
+ api_request.session_state.update(self.global_state)
+ return api_request
+
class Endpoint(EndpointViewMixin, BaseEndpoint):
"""
Endpoint class that contains link prototypes and maps HTTP requests to those links.
@@ -339,6 +390,12 @@ def get_url_name(self):
def get_url_suffix(self):
return self.url_suffix
+ def get_view_kwargs(self):
+ """
+ :rtype: dict
+ """
+ return {}
+
def get_view(self, **kwargs):
"""
:rtype: view callable
@@ -80,6 +80,12 @@ def get_view_endpoints(self):
"""
return []
+ def get_view_kwargs(self):
+ """
+ :rtype: dict
+ """
+ return {}
+
def get_urls(self):
urlpatterns = self.get_extra_urls()
urls = [endpoint.get_url_object() for endpoint in self.endpoints.itervalues()]
View
@@ -1,8 +1,7 @@
-from django.conf.urls.defaults import patterns
-from django.core.urlresolvers import reverse, RegexURLResolver
+from django.core.urlresolvers import RegexURLResolver
from django.utils.datastructures import SortedDict
-from hyperadmin.endpoints import BaseEndpoint
+from hyperadmin.endpoints import RootEndpoint
from hyperadmin.resources.directory import ResourceDirectory
from hyperadmin.resources.auth import AuthResource
@@ -25,7 +24,7 @@ def items(self):
items = [(key, self[key]) for key, val in items]
return items
-class ResourceSite(BaseEndpoint):
+class ResourceSite(RootEndpoint):
directory_resource_class = ResourceDirectory
auth_resource_class = AuthResource
name = 'hyperadmin'
@@ -34,7 +33,7 @@ def __init__(self, **kwargs):
self.applications = Registry(self)
self.registry = Registry(self)
self.resources_by_urlname = dict()#Registry(self)
- self.media_types = dict()
+ kwargs.setdefault('namespace', kwargs.get('name', self.name))
super(ResourceSite, self).__init__(**kwargs)
def get_url_name(self):
@@ -92,37 +91,14 @@ def register_application(self, app_name, app_class=None, **options):
def record_resource(self, resource):
self.resources_by_urlname[resource.get_url_name()] = resource
- def register_media_type(self, media_type, media_type_handler):
- self.media_types[media_type] = media_type_handler
-
def get_resource(self, resource_adaptor):
return self.registry[resource_adaptor]
- def get_resource_item(self, instance, resource_adaptor=None):
- if resource_adaptor is None:
- resource_adaptor = type(instance)
- resource = self.get_resource(resource_adaptor)
- return resource.get_resource_item(instance)
-
def get_urls(self):
urlpatterns = self.get_extra_urls()
urlpatterns += self.directory_resource.get_urls()
return urlpatterns
- @property
- def urlpatterns(self):
- return self.get_urls()
-
- def get_extra_urls(self):
- return patterns('',)
-
- def urls(self):
- return self, None, self.name
- urls = property(urls)
-
- def get_view_kwargs(self):
- return {'resource_site':self,}
-
def get_login_link(self, api_request, **kwargs):
auth_resource = self.auth_resource.fork(api_request=api_request)
return auth_resource.get_link(**kwargs)
@@ -171,16 +147,6 @@ def register_builtin_media_types(self):
for key, value in BUILTIN_MEDIA_TYPES.iteritems():
self.register_media_type(key, value)
- def reverse(self, name, *args, **kwargs):
- return reverse('%s:%s' % (self.name, name), args=args, kwargs=kwargs)#, current_app=self.app_name)
-
- def get_absolute_url(self):
- return self.site_resource.get_absolute_url()
-
- def generate_response(self, media_type, content_type, link, state):
- request = state.endpoint.api_request.request
- return media_type.serialize(request=request, content_type=content_type, link=link, state=state)
-
def get_resource_from_urlname(self, urlname):
return self.resources_by_urlname.get(urlname, None)
Oops, something went wrong. Retry.

0 comments on commit a7500ca

Please sign in to comment.