<commit_before>"""
Resource classes for powering the public facing API go here. These classes proxy functionality from the collections/virtual API.
"""
from hyperadmin.sites import BaseResourceSite
from hyperadmin.resources import BaseResource
from hyperadmin.resources.directory import ResourceDirectory
from hyperadmin.resources.endpoints import ResourceEndpoint
from hyperadmin.links import LinkPrototype, LinkCollectionProvider
from hyperadmin.states import EndpointState
from hyperadmin.resources.hyperobjects import ResourceItem
from hyperadmin.apirequests import InternalAPIRequest

from django.conf.urls.defaults import patterns, url, include


class ChainedAPIRequest(InternalAPIRequest):
    def __init__(self, api_request, inner_site, outer_site, state, 
                 path='/', url_args=[], url_kwargs={}, **kwargs):
        self.outer_api_request = api_request
        self.outer_site = outer_site
        url_args = api_request.url_args
        url_kwargs = api_request.url_kwargs
        self.state = state
        kwargs.setdefault('payload', api_request.payload)
        kwargs.setdefault('method', api_request.method)
        kwargs.setdefault('params', api_request.params)
        super(ChainedAPIRequest, self).__init__(inner_site, path, url_args, url_kwargs, **kwargs)
        self.session_state.update(api_request.session_state)
    
    def get_full_path(self):
        #TODO
        return self.outer_api_request.get_full_path()
    
    @property
    def user(self):
        return self.outer_api_request.user
    
    def generate_response(self, link, state):
        return self.outer_api_request.generate_response(link, self.state)
    
    @property
    def request(self):
        return self.outer_api_request.request
    
    def get_link_prototypes(self, endpoint):
        urlname = endpoint.get_url_name()
        try:
            outer_endpoint = self.outer_api_request.get_endpoint(urlname)
        except KeyError:
            return {}
        return self.outer_api_request.get_link_prototypes(outer_endpoint)
    
    def reverse(self, name, *args, **kwargs):
        return self.outer_site.reverse(name, *args, **kwargs)

class ChainedLinkPrototype(LinkPrototype):
    def __init__(self, endpoint, outer_api_request, inner_prototype):
        #endpoint is discarded
        self.outer_api_request = outer_api_request
        self.inner_prototype = inner_prototype
        inner_prototype.get_url = self.get_url
    
    @property
    def outer_endpoint(self):
        return self.outer_api_request.get_endpoint(self.get_url_name())
    
    @property
    def endpoint(self):
        endpoint = self.inner_prototype.endpoint
        return self.api_request.get_endpoint(endpoint.get_url_name())
    
    @property
    def name(self):
        return self.inner_prototype.name
    
    @property
    def resource(self):
        return self.inner_prototype.resource
    
    @property
    def state(self):
        return self.inner_prototype.state
    
    @property
    def common_state(self):
        return self.inner_prototype.common_state
    
    @property
    def api_request(self):
        return self.inner_prototype.api_request
    
    def show_link(self, **kwargs):
        #TODO check if link resolves on outer_endpoint
        return self.inner_prototype.show_link(**kwargs)
    
    def get_link(self, **link_kwargs):
        return self.inner_prototype.get_link(**link_kwargs)
    
    def handle_submission(self, link, submit_kwargs):
        return self.inner_prototype.handle_submission(link, submit_kwargs)
    
    def get_url(self, **kwargs):
        return self.endpoint.get_url(**kwargs)
    
    def get_url_name(self):
        return self.endpoint.get_url_name()

#this is a mouthful
class PublicEndpointStateLinkCollectionProvider(LinkCollectionProvider):
    def _get_link_functions(self, attr):
        functions = super(PublicEndpointStateLinkCollectionProvider, self)._get_link_functions(attr)
        #TODO these inner links need post-processing
        inner_links = getattr(self.container.inner_state.links, attr)
        functions.append(inner_links)
        return functions

class PublicEndpointState(EndpointState):
    #TODO links should consult inner_state, rewrite urls if they exist
    #get_namespaces
    
    link_collector_class = PublicEndpointStateLinkCollectionProvider
    
    @property
    def inner_endpoint(self):
        return self.endpoint.get_inner_endpoint()
    
    @property
    def inner_state(self):
        return self.inner_endpoint.state
    
    def get_item(self):
        if self.inner_state.item:
            return self.endpoint.get_resource_item(self.inner_state.item)
        return None
    item = property(get_item)
    
    def get_resource_items(self):
        instances = self.inner_state.get_resource_items()
        return [self.endpoint.get_resource_item(instance) for instance in instances]

class PublicResourceItem(ResourceItem):
    """
    Where instance is an inner resource item
    """
    @property
    def form(self):
        return self.instance.form
    
    def get_prompt(self):
        return self.instance.get_prompt()
    
    #links
    #get_resource_items
    #get_absolute_url
    #get_namespaces
    #get_link

class PublicMixin(object):
    state_class = PublicEndpointState
    resource_item_class = PublicResourceItem
    inner_endpoint = None
    
    def get_inner_apirequest_kwargs(self, **kwargs):
        params = {'api_request':self.api_request,
                  'inner_site':self.get_inner_site(),
                  'outer_site':self.site,
                  'path':self.api_request.get_full_path(),
                  'state':self.state,}
        params.update(kwargs)
        return params
    
    def get_inner_site(self):
        return self.inner_endpoint.site
    
    def get_inner_apirequest(self):
        if not hasattr(self, 'inner_apirequest'):
            if 'inner_apirequest' not in self.api_request.session_state:
                kwargs = self.get_inner_apirequest_kwargs()
                inner_apirequest = ChainedAPIRequest(**kwargs)
                self.api_request.session_state['inner_apirequest'] = inner_apirequest
            self.inner_apirequest = self.api_request.session_state['inner_apirequest']
        return self.inner_apirequest
    
    def get_inner_endpoint(self):
        if self.api_request:
            if not hasattr(self, 'bound_inner_endpoint'):
                inner_apirequest = self.get_inner_apirequest()
                urlname = self.get_url_name()
                self.bound_inner_endpoint = inner_apirequest.get_endpoint(urlname)
            return self.bound_inner_endpoint
        return self.inner_endpoint
    
    #def get_url_name(self):
    #    return self.inner_endpoint.get_url_name()
    
    def get_url_suffix(self):
        ending = self.inner_endpoint.get_url_suffix()
        if ending.startswith('^'):
            ending = ending[1:]
        if self.url_suffix:
            return self.url_suffix + ending<commit_msg>minor fix to get url name of a public endpoint<commit_after>"""
Resource classes for powering the public facing API go here. These classes proxy functionality from the collections/virtual API.
"""
from hyperadmin.sites import BaseResourceSite
from hyperadmin.resources import BaseResource
from hyperadmin.resources.directory import ResourceDirectory
from hyperadmin.resources.endpoints import ResourceEndpoint
from hyperadmin.links import LinkPrototype, LinkCollectionProvider
from hyperadmin.states import EndpointState
from hyperadmin.resources.hyperobjects import ResourceItem
from hyperadmin.apirequests import InternalAPIRequest

from django.conf.urls.defaults import patterns, url, include


class ChainedAPIRequest(InternalAPIRequest):
    def __init__(self, api_request, inner_site, outer_site, state, 
                 path='/', url_args=[], url_kwargs={}, **kwargs):
        self.outer_api_request = api_request
        self.outer_site = outer_site
        url_args = api_request.url_args
        url_kwargs = api_request.url_kwargs
        self.state = state
        kwargs.setdefault('payload', api_request.payload)
        kwargs.setdefault('method', api_request.method)
        kwargs.setdefault('params', api_request.params)
        super(ChainedAPIRequest, self).__init__(inner_site, path, url_args, url_kwargs, **kwargs)
        self.session_state.update(api_request.session_state)
    
    def get_full_path(self):
        #TODO
        return self.outer_api_request.get_full_path()
    
    @property
    def user(self):
        return self.outer_api_request.user
    
    def generate_response(self, link, state):
        return self.outer_api_request.generate_response(link, self.state)
    
    @property
    def request(self):
        return self.outer_api_request.request
    
    def get_link_prototypes(self, endpoint):
        urlname = endpoint.get_url_name()
        try:
            outer_endpoint = self.outer_api_request.get_endpoint(urlname)
        except KeyError:
            return {}
        return self.outer_api_request.get_link_prototypes(outer_endpoint)
    
    def reverse(self, name, *args, **kwargs):
        return self.outer_site.reverse(name, *args, **kwargs)

class ChainedLinkPrototype(LinkPrototype):
    def __init__(self, endpoint, outer_api_request, inner_prototype):
        #endpoint is discarded
        self.outer_api_request = outer_api_request
        self.inner_prototype = inner_prototype
        inner_prototype.get_url = self.get_url
    
    @property
    def outer_endpoint(self):
        return self.outer_api_request.get_endpoint(self.get_url_name())
    
    @property
    def endpoint(self):
        endpoint = self.inner_prototype.endpoint
        return self.api_request.get_endpoint(endpoint.get_url_name())
    
    @property
    def name(self):
        return self.inner_prototype.name
    
    @property
    def resource(self):
        return self.inner_prototype.resource
    
    @property
    def state(self):
        return self.inner_prototype.state
    
    @property
    def common_state(self):
        return self.inner_prototype.common_state
    
    @property
    def api_request(self):
        return self.inner_prototype.api_request
    
    def show_link(self, **kwargs):
        #TODO check if link resolves on outer_endpoint
        return self.inner_prototype.show_link(**kwargs)
    
    def get_link(self, **link_kwargs):
        return self.inner_prototype.get_link(**link_kwargs)
    
    def handle_submission(self, link, submit_kwargs):
        return self.inner_prototype.handle_submission(link, submit_kwargs)
    
    def get_url(self, **kwargs):
        return self.endpoint.get_url(**kwargs)
    
    def get_url_name(self):
        return self.endpoint.get_url_name()

#this is a mouthful
class PublicEndpointStateLinkCollectionProvider(LinkCollectionProvider):
    def _get_link_functions(self, attr):
        functions = super(PublicEndpointStateLinkCollectionProvider, self)._get_link_functions(attr)
        #TODO these inner links need post-processing
        inner_links = getattr(self.container.inner_state.links, attr)
        functions.append(inner_links)
        return functions

class PublicEndpointState(EndpointState):
    #TODO links should consult inner_state, rewrite urls if they exist
    #get_namespaces
    
    link_collector_class = PublicEndpointStateLinkCollectionProvider
    
    @property
    def inner_endpoint(self):
        return self.endpoint.get_inner_endpoint()
    
    @property
    def inner_state(self):
        return self.inner_endpoint.state
    
    def get_item(self):
        if self.inner_state.item:
            return self.endpoint.get_resource_item(self.inner_state.item)
        return None
    item = property(get_item)
    
    def get_resource_items(self):
        instances = self.inner_state.get_resource_items()
        return [self.endpoint.get_resource_item(instance) for instance in instances]

class PublicResourceItem(ResourceItem):
    """
    Where instance is an inner resource item
    """
    @property
    def form(self):
        return self.instance.form
    
    def get_prompt(self):
        return self.instance.get_prompt()
    
    #links
    #get_resource_items
    #get_absolute_url
    #get_namespaces
    #get_link

class PublicMixin(object):
    state_class = PublicEndpointState
    resource_item_class = PublicResourceItem
    inner_endpoint = None
    
    def get_inner_apirequest_kwargs(self, **kwargs):
        params = {'api_request':self.api_request,
                  'inner_site':self.get_inner_site(),
                  'outer_site':self.site,
                  'path':self.api_request.get_full_path(),
                  'state':self.state,}
        params.update(kwargs)
        return params
    
    def get_inner_site(self):
        return self.inner_endpoint.site
    
    def get_inner_apirequest(self):
        if not hasattr(self, 'inner_apirequest'):
            if 'inner_apirequest' not in self.api_request.session_state:
                kwargs = self.get_inner_apirequest_kwargs()
                inner_apirequest = ChainedAPIRequest(**kwargs)
                self.api_request.session_state['inner_apirequest'] = inner_apirequest
            self.inner_apirequest = self.api_request.session_state['inner_apirequest']
        return self.inner_apirequest
    
    def get_inner_endpoint(self):
        if self.api_request:
            if not hasattr(self, 'bound_inner_endpoint'):
                inner_apirequest = self.get_inner_apirequest()
                urlname = self.get_url_name()
                self.bound_inner_endpoint = inner_apirequest.get_endpoint(urlname)
            return self.bound_inner_endpoint
        return self.inner_endpoint
    
    def get_base_url_name(self):
        return self.inner_endpoint.get_base_url_name()
    
    def get_url_suffix(self):
        ending = self.inner_endpoint.get_url_suffix()
        if ending.startswith('^'):
            ending = ending[1:]
        if self.url_suffix:
            return self.url_suffix + ending
{'fraction_non_alphanumeric': 0.07821466524973432, 'fraction_numerical': 0.00014169323414806942, 'mean_word_length': 2.9853190287972895, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4306242', 'n_tokens_mistral': 4006, 'n_tokens_neox': 3958, 'n_words': 798}