<commit_before>import webapp2

from time import mktime
from wsgiref.handlers import format_date_time

from google.appengine.api import memcache

import tba_config

from helpers.user_bundle import UserBundle


class CacheableHandler(webapp2.RequestHandler):
    """
    Provides a standard way of caching the output of pages.
    Currently only supports logged-out pages.
    """

    def __init__(self, *args, **kw):
        super(CacheableHandler, self).__init__(*args, **kw)
        self._cache_expiration = 0
        self._cache_key = ""
        self._cache_version = 0

        # Cache all pages for 61 seconds, unless overwritten.
        if self.response is not None:
            self.response.headers['Cache-Control'] = 'public, max-age=61'
            self.response.headers['Pragma'] = 'Public'

    @property
    def cache_key(self):
        return "{}:{}:{}".format(
            self._cache_key,
            self._cache_version,
            tba_config.CONFIG["static_resource_version"])

    def get(self, *args, **kw):
        cached_response = self._read_cache()
        if cached_response:
            self.response.headers = cached_response.headers
            self.response.out.write(cached_response.body)
        else:
            self.response.out.write(self._render(*args, **kw))
            self._write_cache(self.response)

    def _has_been_modified_since(self, datetime):
        last_modified = format_date_time(mktime(datetime.timetuple()))
        if_modified_since = self.request.headers.get('If-Modified-Since')
        if if_modified_since and if_modified_since == last_modified:
            self.response.set_status(304)
            return False
        else:
            self.response.headers['Last-Modified'] = last_modified
            return True

    def memcacheFlush(self):
        memcache.delete(self.cache_key)
        return self.cache_key

    @classmethod
    def clear_cache(cls, *args):
        cache_key = cls.CACHE_KEY_FORMAT.format(*args)
        memcache.delete(cache_key)

    def _read_cache(self):
        return memcache.get(self.cache_key)

    def _render(self):
        raise NotImplementedError("No _render method.")

    def _write_cache(self, response):
        if tba_config.CONFIG["memcache"]:
            memcache.set(self.cache_key, response, self._cache_expiration)


class LoggedInHandler(webapp2.RequestHandler):
    """
    Provides a base set of functionality for pages that need logins.
    Currently does not support caching as easily as CacheableHandler.
    """

    def __init__(self, *args, **kw):
        super(LoggedInHandler, self).__init__(*args, **kw)
        self.user_bundle = UserBundle()
        self.template_values = {
            "user_bundle": self.user_bundle
        }

    def _require_admin(self):
        self._require_login()
        if not self.user_bundle.is_current_user_admin:
            return self.redirect(self.user_bundle.login_url, abort=True)

    def _require_login(self, target_url="/"):
        if not self.user_bundle.user:
            return self.redirect(
                self.user_bundle.create_login_url(target_url),
                abort=True
            )
<commit_msg>make cache key generation available as a classmethod<commit_after>import webapp2

from time import mktime
from wsgiref.handlers import format_date_time

from google.appengine.api import memcache

import tba_config

from helpers.user_bundle import UserBundle


class CacheableHandler(webapp2.RequestHandler):
    """
    Provides a standard way of caching the output of pages.
    Currently only supports logged-out pages.
    """
    CACHE_VERSION = 0

    def __init__(self, *args, **kw):
        super(CacheableHandler, self).__init__(*args, **kw)
        self._cache_expiration = 0
        self._cache_key = ""

        # Cache all pages for 61 seconds, unless overwritten.
        if self.response is not None:
            self.response.headers['Cache-Control'] = 'public, max-age=61'
            self.response.headers['Pragma'] = 'Public'

    @property
    def full_cache_key(self):
        return self._get_full_cache_key(self._cache_key)

    @classmethod
    def _get_full_cache_key(cls, cache_key):
        return "{}:{}:{}".format(
            cache_key,
            cls.CACHE_VERSION,
            tba_config.CONFIG["static_resource_version"])

    def get(self, *args, **kw):
        cached_response = self._read_cache()
        if cached_response:
            self.response.out.write(cached_response.body)
            self.response.headers = cached_response.headers
        else:
            self.response.out.write(self._render(*args, **kw))
            self._write_cache(self.response)

    def _has_been_modified_since(self, datetime):
        last_modified = format_date_time(mktime(datetime.timetuple()))
        if_modified_since = self.request.headers.get('If-Modified-Since')
        if if_modified_since and if_modified_since == last_modified:
            self.response.set_status(304)
            return False
        else:
            self.response.headers['Last-Modified'] = last_modified
            return True

    def memcacheFlush(self):
        memcache.delete(self.full_cache_key)
        return self.full_cache_key

    @classmethod
    def clear_cache(cls, *args):
        full_cache_key = cls._get_full_cache_key(cls.CACHE_KEY_FORMAT.format(*args))
        memcache.delete(full_cache_key)

    def _read_cache(self):
        return memcache.get(self.full_cache_key)

    def _render(self):
        raise NotImplementedError("No _render method.")

    def _write_cache(self, response):
        if tba_config.CONFIG["memcache"]:
            memcache.set(self.full_cache_key, response, self._cache_expiration)


class LoggedInHandler(webapp2.RequestHandler):
    """
    Provides a base set of functionality for pages that need logins.
    Currently does not support caching as easily as CacheableHandler.
    """

    def __init__(self, *args, **kw):
        super(LoggedInHandler, self).__init__(*args, **kw)
        self.user_bundle = UserBundle()
        self.template_values = {
            "user_bundle": self.user_bundle
        }

    def _require_admin(self):
        self._require_login()
        if not self.user_bundle.is_current_user_admin:
            return self.redirect(self.user_bundle.login_url, abort=True)

    def _require_login(self, target_url="/"):
        if not self.user_bundle.user:
            return self.redirect(
                self.user_bundle.create_login_url(target_url),
                abort=True
            )

{'fraction_non_alphanumeric': 0.09599268627152217, 'fraction_numerical': 0.0036568642389151304, 'mean_word_length': 2.679372197309417, 'pattern_counts': {'":': 2, '<': 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': '2737291', 'n_tokens_mistral': 1945, 'n_tokens_neox': 1894, 'n_words': 399}