<commit_before>import logging
import os.path
import re

import adhocracy.model
from adhocracy import i18n
from adhocracy.lib.helpers.adhocracy_service import RESTAPI
from adhocracy.lib import util
from adhocracy.lib.auth.authorization import has
from adhocracy.lib.outgoing_link import rewrite_urls


from lxml.html import parse, tostring
from pylons import config

log = logging.getLogger(__name__)


class StaticPageBase(object):

    def __init__(self, key, lang, body, title, css_classes=[]):
        self.key = key
        self.lang = lang
        self.title = title
        self.body = body
        self.css_classes = css_classes

    @staticmethod
    def get(key, lang):
        fn = os.path.basename(key) + '.' + lang + '.html'
        filename = util.get_path('page', fn)
        if filename is None:
            return None
        try:
            root = parse(filename)
        except IOError:
            return None
        try:
            body = root.find('.//body')
            title = root.find('.//title').text
        except AttributeError:
            log.debug(u'Failed to parse static document ' + filename)
            return None
        body.tag = 'span'
        return FileStaticPage(key, lang, tostring(body), title)

    def commit(self):
        """ Persist changes to this object. """
        raise NotImplementedError()

    @staticmethod
    def all():
        raise NotImplementedError()

    def save(self):
        raise NotImplementedError()

    @staticmethod
    def create(key, lang, title, body):
        raise NotImplementedError()

    @staticmethod
    def is_editable():
        return False


class FileStaticPage(StaticPageBase):

    @staticmethod
    def get(key, languages):

        for lang in languages:
            fn = os.path.basename(key) + '.' + lang + '.html'
            filename = util.get_path('page', fn)
            if filename is not None:
                try:
                    root = parse(filename)
                except IOError:
                    return None
                try:
                    body = root.find('.//body')
                    title = root.find('.//title').text
                except AttributeError:
                    log.debug(
                        u'Failed to parse static document ' + filename)
                    return None
                body.tag = 'span'
                return FileStaticPage(key, lang, tostring(body), title)
        return None


class ExternalStaticPage(StaticPageBase):

    @staticmethod
    def get(key, languages):
        api = RESTAPI()
        result = api.staticpage_get(key)
        page = result.json()
        if page is None:
            return None
        return ExternalStaticPage(key, page['lang'], page['body'], page['title'])

_BACKENDS = {
    'filesystem': FileStaticPage,
    'database': adhocracy.model.StaticPage,
    'external': ExternalStaticPage,
}

STATICPAGE_KEY = re.compile(r'^[a-z0-9_-]+$')


def get_backend():
    backend_id = config.get('adhocracy.staticpage_backend', 'filesystem')
    return _BACKENDS[backend_id]


def can_edit():<commit_msg>Better error handling for non-existing static pages<commit_after>import logging
import os.path
import re

import adhocracy.model
from adhocracy import i18n
from adhocracy.lib.helpers.adhocracy_service import RESTAPI
from adhocracy.lib import util
from adhocracy.lib.auth.authorization import has
from adhocracy.lib.outgoing_link import rewrite_urls


from lxml.html import parse, tostring
from pylons import config

log = logging.getLogger(__name__)


class StaticPageBase(object):

    def __init__(self, key, lang, body, title, css_classes=[]):
        self.key = key
        self.lang = lang
        self.title = title
        self.body = body
        self.css_classes = css_classes

    @staticmethod
    def get(key, lang):
        fn = os.path.basename(key) + '.' + lang + '.html'
        filename = util.get_path('page', fn)
        if filename is None:
            return None
        try:
            root = parse(filename)
        except IOError:
            return None
        try:
            body = root.find('.//body')
            title = root.find('.//title').text
        except AttributeError:
            log.debug(u'Failed to parse static document ' + filename)
            return None
        body.tag = 'span'
        return FileStaticPage(key, lang, tostring(body), title)

    def commit(self):
        """ Persist changes to this object. """
        raise NotImplementedError()

    @staticmethod
    def all():
        raise NotImplementedError()

    def save(self):
        raise NotImplementedError()

    @staticmethod
    def create(key, lang, title, body):
        raise NotImplementedError()

    @staticmethod
    def is_editable():
        return False


class FileStaticPage(StaticPageBase):

    @staticmethod
    def get(key, languages):

        for lang in languages:
            fn = os.path.basename(key) + '.' + lang + '.html'
            filename = util.get_path('page', fn)
            if filename is not None:
                try:
                    root = parse(filename)
                except IOError:
                    return None
                try:
                    body = root.find('.//body')
                    title = root.find('.//title').text
                except AttributeError:
                    log.debug(
                        u'Failed to parse static document ' + filename)
                    return None
                body.tag = 'span'
                return FileStaticPage(key, lang, tostring(body), title)
        return None


class ExternalStaticPage(StaticPageBase):

    @staticmethod
    def get(key, languages):
        api = RESTAPI()
        result = api.staticpage_get(key)
        page = result.json()
        if page is None or 'errors' in page:
            return None
        return ExternalStaticPage(key, page['lang'], page['body'], page['title'])

_BACKENDS = {
    'filesystem': FileStaticPage,
    'database': adhocracy.model.StaticPage,
    'external': ExternalStaticPage,
}

STATICPAGE_KEY = re.compile(r'^[a-z0-9_-]+$')


def get_backend():
    backend_id = config.get('adhocracy.staticpage_backend', 'filesystem')
    return _BACKENDS[backend_id]


def can_edit():
{'fraction_non_alphanumeric': 0.09923542529467984, 'fraction_numerical': 0.0012742911755336094, 'mean_word_length': 2.0480582524271846, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, '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': '7225840', 'n_tokens_mistral': 1800, 'n_tokens_neox': 1702, 'n_words': 469}