def testBasic(self):
        c = LocalSyncCache(id="test1")
        c["key1"] = "value1"
        self.assertEqual(c, {'key1': 'value1'})

        cache.set("test1", time.time())

        c.check_state()
        self.assertEqual(c, {})

        cache_information = LocalSyncCache.get_cache_information()
        self.assertEqual(len(cache_information), 1)
    def testBasic(self):
        c = LocalSyncCache(id="test1")
        c["key1"] = "value1"
        self.assertEqual(c, {'key1': 'value1'})

        cache.set("test1", time.time())

        c.check_state()
        self.assertEqual(c, {})

        cache_information = LocalSyncCache.get_cache_information()
        self.assertEqual(len(cache_information), 1)
    def testBasic(self):
        c = LocalSyncCache(id="test1")
        c["key1"] = "value1"
        assert_pformat_equal(c, {"key1": "value1"})

        cache.set("test1", time.time())

        c.check_state()
        assert_pformat_equal(c, {})

        cache_information = LocalSyncCache.get_cache_information()
        assert_pformat_equal(len(cache_information), 1)
Example #4
0
class SiteAliasManager(models.Manager):
    ALIAS_CACHE = None

    def get_from_host(self, current_host):
        if self.ALIAS_CACHE is None:
            # first request after startup / model.save() -> fill the cache
            logger.debug("init LocalSyncCache for SiteAlias cache")
            self.ALIAS_CACHE = LocalSyncCache(id="SiteAliasCache")

        if "string" not in self.ALIAS_CACHE:
            logger.debug("Fill SiteAlias cache")
            self.ALIAS_CACHE["string"] = {}
            self.ALIAS_CACHE["regex"] = []
            queryset = self.all()
            for site_alias in queryset:
                site = site_alias.site
                alias = site_alias.alias

                if site_alias.regex:
                    regex = compile_alias(alias)
                    self.ALIAS_CACHE["regex"].append((regex, site))
                else:
                    self.ALIAS_CACHE["string"][alias.lower()] = site

            self.ALIAS_CACHE["regex"] = tuple(self.ALIAS_CACHE["regex"])
            logger.debug("Alias string cache: %s" %
                         repr(self.ALIAS_CACHE["string"]))
            logger.debug("Alias regex cache: %s" %
                         repr(self.ALIAS_CACHE["regex"]))

        # Try first all string alias:
        try:
            return self.ALIAS_CACHE["string"][current_host]
        except KeyError:
            logger.debug("No site found in string cache for %r" % current_host)

        # Try all regex alias:
        for regex, site in self.ALIAS_CACHE["regex"]:
            match = regex.search(current_host)
            if match is not None:
                return site

        logger.debug("No site found in regex cache for %r" % current_host)
        raise self.model.DoesNotExist("No alias found for %r" % current_host)

    def clear_cache(self):
        if self.ALIAS_CACHE is not None:
            logger.debug("Clear SiteAlias cache")
            self.ALIAS_CACHE.clear()
            logger.debug("Clear DynamicSiteMiddlewareCache cache")
            sites_models.SITE_CACHE.clear()
Example #5
0
class SiteAliasManager(models.Manager):
    ALIAS_CACHE = None

    def get_from_host(self, current_host):
        if self.ALIAS_CACHE is None:
            # first request after startup / model.save() -> fill the cache
            logger.debug("init LocalSyncCache for SiteAlias cache")
            self.ALIAS_CACHE = LocalSyncCache(id="SiteAliasCache")

        if "string" not in self.ALIAS_CACHE:
            logger.debug("Fill SiteAlias cache")
            self.ALIAS_CACHE["string"] = {}
            self.ALIAS_CACHE["regex"] = []
            queryset = self.all()
            for site_alias in queryset:
                site = site_alias.site
                alias = site_alias.alias

                if site_alias.regex:
                    regex = compile_alias(alias)
                    self.ALIAS_CACHE["regex"].append((regex, site))
                else:
                    self.ALIAS_CACHE["string"][alias.lower()] = site

            self.ALIAS_CACHE["regex"] = tuple(self.ALIAS_CACHE["regex"])
            logger.debug("Alias string cache: %s" % repr(self.ALIAS_CACHE["string"]))
            logger.debug("Alias regex cache: %s" % repr(self.ALIAS_CACHE["regex"]))

        # Try first all string alias:
        try:
            return self.ALIAS_CACHE["string"][current_host]
        except KeyError:
            logger.debug("No site found in string cache for %r" % current_host)

        # Try all regex alias:
        for regex, site in self.ALIAS_CACHE["regex"]:
            match = regex.search(current_host)
            if match is not None:
                return site

        logger.debug("No site found in regex cache for %r" % current_host)
        raise self.model.DoesNotExist("No alias found for %r" % current_host)

    def clear_cache(self):
        if self.ALIAS_CACHE is not None:
            logger.debug("Clear SiteAlias cache")
            self.ALIAS_CACHE.clear()
            logger.debug("Clear DynamicSiteMiddlewareCache cache")
            sites_models.SITE_CACHE.clear()
Example #6
0
def show_internals(request):
    apps_info = []
    for app in get_apps():
        model_info = []
        for model in get_models(app):
            model_info.append({
                "name":model._meta.object_name,
            })
        apps_info.append({
            "app_name": app.__name__,
            "app_models": model_info,
        })

    # from http://www.djangosnippets.org/snippets/1434/
    # generate a list of (pattern-name, pattern) tuples
    resolver = urlresolvers.get_resolver(None)
    urlpatterns = sorted([
        (key, value[0][0][0])
        for key, value in resolver.reverse_dict.items()
        if isinstance(key, basestring)
    ])

    context = {
        "title": "Show internals",

        "pid": os.getpid(),
        "cache_information": LocalSyncCache.get_cache_information(),

        "permissions": Permission.objects.all(),

        "urlpatterns": urlpatterns,
        "settings": hightlighter.make_html(
            pformat(get_safe_settings()), source_type="py", django_escape=True
        ),

        "db_backend_name": backend.Database.__name__,
        "db_backend_module": backend.Database.__file__,
        "db_backend_version": getattr(backend.Database, "version", "?"),

        "apps_info": apps_info,

        "db_table_names": sorted(connection.introspection.table_names()),
        "django_tables": sorted(connection.introspection.django_table_names()),

        "request_meta": hightlighter.make_html(
            pformat(request.META), source_type="py", django_escape=True
        ),

        "request_session": hightlighter.make_html(
            pformat(dict(request.session)), source_type="py", django_escape=True
        ),

        "sys_path": sys.path,
        "os_environ": os.environ,
    }
    return context
Example #7
0
def show_internals(request):
    apps_info = []
    for app in get_apps():
        model_info = []
        for model in get_models(app):
            model_info.append({
                "name":model._meta.object_name,
            })
        apps_info.append({
            "app_name": app.__name__,
            "app_models": model_info,
        })


    # Information about the current used url patterns
    urlpatterns = UrlPatternInfo().get_url_info()

    context = {
        "title": "Show internals",

        "pid": os.getpid(),
        "cache_information": LocalSyncCache.get_cache_information(),

        "permissions": Permission.objects.all(),

        "urlpatterns": urlpatterns,
        "settings": hightlighter.make_html(
            pformat(get_safe_settings()), source_type="py", django_escape=True
        ),

        "db_backend_name": backend.Database.__name__,
        "db_backend_module": backend.Database.__file__,
        "db_backend_version": getattr(backend.Database, "version", "?"),

        "apps_info": apps_info,

        "db_table_names": sorted(connection.introspection.table_names()),
        "django_tables": sorted(connection.introspection.django_table_names()),

        "request_meta": hightlighter.make_html(
            pformat(request.META), source_type="py", django_escape=True
        ),

        "request_session": hightlighter.make_html(
            pformat(dict(request.session)), source_type="py", django_escape=True
        ),

        "sys_path": sys.path,
        "os_environ": os.environ,
    }
    return context
Example #8
0
    def testLocalSyncCacheMiddleware(self):
        middleware = LocalSyncCacheMiddleware()

        c1 = LocalSyncCache(id="testLocalSyncCacheMiddleware1")
        c2 = LocalSyncCache(id="testLocalSyncCacheMiddleware1",
                            unique_ids=False)

        c3 = LocalSyncCache(id="testLocalSyncCacheMiddleware2")

        assert_pformat_equal(len(LocalSyncCache.CACHES), 3)

        c1["c1"] = "foo"
        c2["c2"] = "bar"
        c3["foo"] = "bar"

        middleware.process_request(None)

        assert_pformat_equal(c1, {"c1": "foo"})
        assert_pformat_equal(c2, {"c2": "bar"})
        assert_pformat_equal(c3, {"foo": "bar"})

        c1.clear()
        assert_pformat_equal(c1, {})

        # In a "new request" all the same caches should be cleared
        middleware.process_request(None)
        assert_pformat_equal(c2, {})

        # Other caches should be not affected by clear()
        assert_pformat_equal(c3, {"foo": "bar"})

        c1["c1"] = "foo2"
        c2["c2"] = "bar2"

        middleware.process_request(None)

        assert_pformat_equal(c1, {"c1": "foo2"})
        assert_pformat_equal(c2, {"c2": "bar2"})
        assert_pformat_equal(c3, {"foo": "bar"})

        c2.clear()
        assert_pformat_equal(c2, {})

        # In a "new request" all the same caches should be cleared
        middleware.process_request(None)
        assert_pformat_equal(c1, {})

        #        print LocalSyncCache.pformat_cache_information()
        cache_information = LocalSyncCache.get_cache_information()
        assert_pformat_equal(len(cache_information), 3)
        for item in cache_information:
            instance = item["instance"]
            assert_pformat_equal(instance.request_counter, 4)

            if instance.id == "testLocalSyncCacheMiddleware2":
                assert_pformat_equal(instance.own_clear_counter, 0)
                assert_pformat_equal(instance.ext_clear_counter, 0)
                assert_pformat_equal(instance, {"foo": "bar"})
            else:
                assert_pformat_equal(instance.own_clear_counter, 1)
                assert_pformat_equal(instance.ext_clear_counter, 1)
                assert_pformat_equal(instance, {})
Example #9
0
    def testMulti(self):
        assert_pformat_equal(len(LocalSyncCache.CACHES), 0)
        c1 = LocalSyncCache(id="test1")
        assert_pformat_equal(len(LocalSyncCache.CACHES), 1)
        c2 = LocalSyncCache(id="test1", unique_ids=False)
        assert_pformat_equal(len(LocalSyncCache.CACHES), 2)
        c1["c1"] = "foo"
        c2["c2"] = "bar"
        assert_pformat_equal(c1, {"c1": "foo"})
        assert_pformat_equal(c2, {"c2": "bar"})

        c1.check_state()
        c2.check_state()

        assert_pformat_equal(c1, {"c1": "foo"})
        assert_pformat_equal(c2, {"c2": "bar"})

        c1.clear()
        assert_pformat_equal(c1, {})

        # In a "new request" all the same caches should be cleared
        c2.check_state()
        assert_pformat_equal(c2, {})

        cache_information = LocalSyncCache.get_cache_information()
        assert_pformat_equal(len(cache_information), 2)
Example #10
0
 def testPformatCacheInfo(self):
     LocalSyncCache(id="FooBar")
     txt = LocalSyncCache.pformat_cache_information()
     self.assertTrue("id: FooBar" in txt)
     self.assertTrue("instance: {}" in txt)
     self.assertTrue("cleared: False" in txt)
Example #11
0
 def testEmptyPformatCacheInfo(self):
     txt = LocalSyncCache.pformat_cache_information()
     assert_pformat_equal(txt, "")
Example #12
0
 def testUniqueID(self):
     c1 = LocalSyncCache(id="test1")
     self.assertRaises(AssertionError, LocalSyncCache, id="test1")
Example #13
0
from django_tools import model_utils
from django_tools.local_sync_cache.local_sync_cache import LocalSyncCache
from django_tools.models import UpdateInfoBaseModel
from django_tools.utils import installed_apps_utils
from django_tools.utils.messages import failsafe_message

from pylucid_project.apps.pylucid.fields import RootAppChoiceField
from pylucid_project.apps.pylucid.signals_handlers import update_plugin_urls
from pylucid_project.base_models.base_models import BaseModelManager, BaseModel
from pylucid_project.system.pylucid_plugins import PYLUCID_PLUGINS


TAG_INPUT_HELP_URL = \
"http://google.com/search?q=cache:django-tagging.googlecode.com/files/tagging-0.2-overview.html#tag-input"

_URL_RESOLVER_CACHE = LocalSyncCache(id="PluginPage_url_resolver")


class PluginPageManager(BaseModelManager):
    """
    TODO: In next release witch has a update routine: we should switch:
        from plugin_instance.installed_apps_string to plugin_instance.pkg_string
    """
    _APP_CHOICES = None

    def get_app_choices(self):
        """
        Generate a choice list with all views witch can handle a empty root url.
        But PyLucid can only handle own plugins, see:
            http://trac.pylucid.net/ticket/333
        """
    def testMulti(self):
        assert_pformat_equal(len(LocalSyncCache.CACHES), 0)
        c1 = LocalSyncCache(id="test1")
        assert_pformat_equal(len(LocalSyncCache.CACHES), 1)
        c2 = LocalSyncCache(id="test1", unique_ids=False)
        assert_pformat_equal(len(LocalSyncCache.CACHES), 2)
        c1["c1"] = "foo"
        c2["c2"] = "bar"
        assert_pformat_equal(c1, {"c1": "foo"})
        assert_pformat_equal(c2, {"c2": "bar"})

        c1.check_state()
        c2.check_state()

        assert_pformat_equal(c1, {"c1": "foo"})
        assert_pformat_equal(c2, {"c2": "bar"})

        c1.clear()
        assert_pformat_equal(c1, {})

        # In a "new request" all the same caches should be cleared
        c2.check_state()
        assert_pformat_equal(c2, {})

        cache_information = LocalSyncCache.get_cache_information()
        assert_pformat_equal(len(cache_information), 2)
 def testEmptyPformatCacheInfo(self):
     txt = LocalSyncCache.pformat_cache_information()
     self.assertEqual(txt, "")
Example #16
0
from django.utils.importlib import import_module
from django.utils.log import getLogger
from django.views.decorators.csrf import csrf_protect

from django_tools.local_sync_cache.local_sync_cache import LocalSyncCache

from pylucid_project.utils.python_tools import has_init_file
from pylucid_project.utils.url_debug import log_urls, debug_log_urls

# see: http://www.pylucid.org/permalink/443/how-to-display-debug-information
log = getLogger("pylucid.pylucid_plugins")

# PYLUCID_PLUGINS = None

_PLUGIN_OBJ_CACHE = {}  # cache for PyLucidPlugin.get_plugin_object()
_PLUGIN_URL_CACHE = LocalSyncCache(
    id="plugin_url_cache")  # cache for PyLucidPlugin.get_prefix_urlpatterns()


class PluginNotOnSite(Exception):
    """ PluginPage doesn't exist on current page. """
    pass


# Use django-tools local sync cache for sync the plugin urls in
# a multi-threaded environment.
PLUGIN_URLS_SYNC_DICT = LocalSyncCache(id="plugin url patterns")


class PluginURLPattern(RegexURLResolver):
    """
    Handle all url patterns from PyLucid plugins.
Example #17
0
def show_internals(request):
    apps_info = []
    for app in get_apps():
        model_info = []
        for model in get_models(app):
            model_info.append({
                "name":model._meta.object_name,
            })
        apps_info.append({
            "app_name": app.__name__,
            "app_models": model_info,
        })


    # Information about the current used url patterns
    urlpatterns = UrlPatternInfo().get_url_info()

    # Create a dict from RequestContext
    request_context = RequestContext(request)
    keys = set()
    for context_dict in request_context.dicts:
        keys = keys.union(set(context_dict.keys()))
    request_context_info = {}
    for key in keys:
        request_context_info[key] = request_context[key]

    try:
        cnonce_size = sys.getsizeof(CNONCE_CACHE)  # New in version 2.6
    except (AttributeError, TypeError):  # PyPy raised a TypeError
        cnonce_size = None

    context = {
        "title": "Show internals",

        "pid": os.getpid(),
        "cache_information": LocalSyncCache.get_cache_information(),

        "permissions": Permission.objects.all(),

        "urlpatterns": urlpatterns,
        "request_context":hightlighted_pformat(request_context_info),
        "settings": hightlighted_pformat(get_safe_settings()),

        "db_backend_name": backend.Database.__name__,
        "db_backend_module": backend.Database.__file__,
        "db_backend_version": getattr(backend.Database, "version", "?"),

        "apps_info": apps_info,

        "db_table_names": sorted(connection.introspection.table_names()),
        "django_tables": sorted(connection.introspection.django_table_names()),

        "request_meta": hightlighter.make_html(
            pformat(request.META), source_type="py", django_escape=True
        ),

        "request_session": hightlighter.make_html(
            pformat(dict(request.session)), source_type="py", django_escape=True
        ),

        "sys_path": sys.path,
        "os_environ": os.environ,

        # Information of the cache usage
        # from FetchFromCacheMiddleware (if settings.COUNT_FETCH_FROM_CACHE != True: all values are None):
        "local_cache_requests": LOCAL_CACHE_INFO["requests"],
        "local_cache_request_hits": LOCAL_CACHE_INFO["request hits"],
        "global_cache_requests": cache.get(CACHE_REQUESTS),
        "global_cache_request_hits":  cache.get(CACHE_REQUEST_HITS),

        # from UpdateCacheMiddleware (if settings.COUNT_UPDATE_CACHE != True: all values are None):
        "local_cache_responses": LOCAL_CACHE_INFO["responses"],
        "local_cache_response_hits": LOCAL_CACHE_INFO["response hits"],
        "global_cache_responses": cache.get(CACHE_RESPONSES),
        "global_cache_response_hits":  cache.get(CACHE_RESPONSE_HITS),

        # Information about auth cnonce usage:
        "cnonce_count": len(CNONCE_CACHE),
        "cnonce_size": cnonce_size,
        "used_cnonces": tuple(sorted(CNONCE_CACHE.keys())),
    }
    return context
Example #18
0
    def testMulti(self):
        self.assertEqual(len(LocalSyncCache.CACHES), 0)
        c1 = LocalSyncCache(id="test1")
        self.assertEqual(len(LocalSyncCache.CACHES), 1)
        c2 = LocalSyncCache(id="test1", unique_ids=False)
        self.assertEqual(len(LocalSyncCache.CACHES), 2)
        c1["c1"] = "foo"
        c2["c2"] = "bar"
        self.assertEqual(c1, {'c1': 'foo'})
        self.assertEqual(c2, {'c2': 'bar'})

        c1.check_state()
        c2.check_state()

        self.assertEqual(c1, {'c1': 'foo'})
        self.assertEqual(c2, {'c2': 'bar'})

        c1.clear()
        self.assertEqual(c1, {})

        # In a "new request" all the same caches should be cleared
        c2.check_state()
        self.assertEqual(c2, {})

        cache_information = LocalSyncCache.get_cache_information()
        self.assertEqual(len(cache_information), 2)
Example #19
0
class PageMeta(BaseModel, UpdateInfoBaseModel, PermissionsBase):
    """
    Meta data for PageContent or PluginPage

    inherited attributes from UpdateInfoBaseModel:
        createtime     -> datetime of creation
        lastupdatetime -> datetime of the last change
        createby       -> ForeignKey to user who created this entry
        lastupdateby   -> ForeignKey to user who has edited this entry
        
    inherited from PermissionsBase:
        validate_permit_group()
        check_sub_page_permissions()
    """
    objects = PageMetaManager()
    on_site = CurrentSiteManager()

    pagetree = models.ForeignKey("pylucid.PageTree") # Should we add null=True, blank=True here? see clean_fields() below
    language = models.ForeignKey("pylucid.Language")

    name = models.CharField(blank=True, max_length=150,
        help_text="Sort page name (for link text in e.g. menu)"
    )
    title = models.CharField(blank=True, max_length=256,
        help_text="A long page title (for e.g. page title or link title text)"
    )

    tags = jQueryTagModelField() # a django-tagging model field modified by django-tools

    keywords = models.CharField(blank=True, max_length=255,
        help_text="Keywords for the html header. (separated by commas)"
    )
    description = models.CharField(blank=True, max_length=255, help_text="For html header")

    robots = models.CharField(blank=True, max_length=255, default="index,follow",
        help_text="for html 'robots' meta content."
    )

    permitViewGroup = models.ForeignKey(Group, related_name="%(class)s_permitViewGroup",
        help_text="Limit viewable this page in this language to a user group?",
        null=True, blank=True,
    )
    # FIXME: Add permitEditGroup, too.
    # e.g.: allow only usergroup X to edit this page in language Y
    # https://github.com/jedie/PyLucid/issues/57

    def clean_fields(self, exclude):
        super(PageMeta, self).clean_fields(exclude)

        message_dict = {}

        try:
            # We can only check the sub pages, if exists ;)
            pagetree = self.pagetree
        except ObjectDoesNotExist:
            # FIXME: Should self.pagetree() field has null=True, blank=True ?
            return

        # Prevents that a unprotected page created below a protected page.
        # TODO: Check this in unittests
        # validate_permit_group() method inherited from PermissionsBase
        self.validate_permit_group("permitViewGroup", exclude, message_dict)

        # Warn user if PageMeta permissions mismatch with sub pages
        # TODO: Check this in unittests
        queryset = PageMeta.objects.filter(pagetree__parent=self.pagetree)
        self.check_sub_page_permissions(# method inherited from PermissionsBase
            ("permitViewGroup",), # TODO: permitEditGroup, read above
            exclude, message_dict, queryset
        )

        if message_dict:
            raise ValidationError(message_dict)

    def recusive_attribute(self, attribute):
        """
        Goes the pagetree back to root and return the first match of attribute if not None.
        
        used e.g.
            with permitViewGroup and permitEditGroup
            from self.validate_permit_group() and self.check_sub_page_permissions()
        """
        parent_pagetree = self.pagetree.parent
        if parent_pagetree is None: # parent is the tree root
            return None

        request = ThreadLocal.get_current_request()
        if request is None:
            # Check only if we are in a request
            return

        queryset = PageMeta.objects.filter(pagetree=parent_pagetree)
        parent_pagemeta = None
        languages = request.PYLUCID.languages # languages are in client prefered order
        for language in languages:
            try:
                parent_pagemeta = queryset.get(language=language)
            except PageMeta.DoesNotExist:
                continue
            else:
                break

        if parent_pagemeta is None:
            return

        if getattr(parent_pagemeta, attribute) is not None:
            # the attribute was set by parent page
            return parent_pagemeta
        else:
            # go down to root
            return parent_pagemeta.recusive_attribute(attribute)

    _url_cache = LocalSyncCache(id="PageMeta_absolute_url")
    def get_absolute_url(self):
        """ absolute url *with* language code (without domain/host part) """
        if self.pk in self._url_cache:
            #print "PageMeta url cache len: %s, pk: %s" % (len(self._url_cache), self.pk)
            return self._url_cache[self.pk]

        lang_code = self.language.code
        page_url = self.pagetree.get_absolute_url()
        url = "/" + lang_code + page_url

        self._url_cache[self.pk] = url
        return url

    _permalink_cache = LocalSyncCache(id="PageMeta_permalink")
    def get_permalink(self):
        """
        return a permalink. Use page slug/name/title or nothing as additional text.
        """
        if self.pk in self._permalink_cache:
            #print "PageMeta permalink_cache len: %s, pk: %s" % (len(self._permalink_cache), self.pk)
            return self._permalink_cache[self.pk]

        # Get the system preferences
        request = ThreadLocal.get_current_request()
        sys_pref = request.PYLUCID.preferences
        sys_pref_form = request.PYLUCID.preferences_form

        use_additions = sys_pref.get("permalink_additions", sys_pref_form.PERMALINK_USE_TITLE)

        do_slugify = False
        if use_additions == sys_pref_form.PERMALINK_USE_TITLE:
            # Append the PageMeta title (language dependent)
            addition_txt = self.get_title()
            do_slugify = True
        elif use_additions == sys_pref_form.PERMALINK_USE_NAME:
            addition_txt = self.get_name()
            do_slugify = True
        elif use_additions == sys_pref_form.PERMALINK_USE_SLUG:
            addition_txt = self.pagetree.slug
        else:
            addition_txt = ""

        if do_slugify:
            addition_txt = slugify(addition_txt)

        url = reverse('PyLucid-permalink', kwargs={'page_id': self.pagetree.id, 'url_rest': addition_txt})
        self._permalink_cache[self.pk] = url
        return url

    def save(self, *args, **kwargs):
        """ reset PageMeta and PageTree url cache """
        # Clean the local url cache dict
        self._url_cache.clear()
        self._permalink_cache.clear()
        self.pagetree._url_cache.clear()

        # FIXME: We must only update the cache for the current SITE not for all sites.
        try:
            cache.smooth_update() # Save "last change" timestamp in django-tools SmoothCacheBackend
        except AttributeError:
            # No SmoothCacheBackend used -> clean the complete cache
            cache.clear()

        return super(PageMeta, self).save(*args, **kwargs)

    def get_site(self):
        """ used e.g. for self.get_absolute_uri() and the admin page """
        return self.pagetree.site
    get_site.short_description = _('on site')
    get_site.allow_tags = False

    def get_other_languages(self):
        return PageMeta.objects.all().filter(pagetree=self.pagetree).exclude(language=self.language)

    def get_title(self):
        """ The page title is optional, if not exist, used the slug from the page tree """
        return self.title or self.get_name()

    def get_name(self):
        return self.name or self.pagetree.slug

    def __unicode__(self):
        return u"PageMeta for page: %r (lang: %s, site: %s)" % (
            self.pagetree.slug, self.language.code, self.get_site().domain
        )

    class Meta:
        app_label = 'pylucid'
        verbose_name_plural = verbose_name = "PageMeta"
        unique_together = (("pagetree", "language"),)
        ordering = ("-lastupdatetime",)
    def testMulti(self):
        self.assertEqual(len(LocalSyncCache.CACHES), 0)
        c1 = LocalSyncCache(id="test1")
        self.assertEqual(len(LocalSyncCache.CACHES), 1)
        c2 = LocalSyncCache(id="test1", unique_ids=False)
        self.assertEqual(len(LocalSyncCache.CACHES), 2)
        c1["c1"] = "foo"
        c2["c2"] = "bar"
        self.assertEqual(c1, {'c1': 'foo'})
        self.assertEqual(c2, {'c2': 'bar'})

        c1.check_state()
        c2.check_state()

        self.assertEqual(c1, {'c1': 'foo'})
        self.assertEqual(c2, {'c2': 'bar'})

        c1.clear()
        self.assertEqual(c1, {})

        # In a "new request" all the same caches should be cleared
        c2.check_state()
        self.assertEqual(c2, {})

        cache_information = LocalSyncCache.get_cache_information()
        self.assertEqual(len(cache_information), 2)
Example #21
0
    def __unicode__(self):
        #        print "DynamicSiteId __unicode__"
        return str(SITE_THREAD_LOCAL.SITE_ID)


def _clear_cache(self):
    logger.debug("Clear SITE_CACHE (The django-tools LocalSyncCache() dict)")
    SITE_CACHE.clear()


if USE_DYNAMIC_SITE_MIDDLEWARE == True:
    # Use the same SITE_CACHE for getting site object by host [1] and get current site by SITE_ID [2]
    # [1] here in DynamicSiteMiddleware._get_site_id_from_host()
    # [2] in django.contrib.sites.models.SiteManager.get_current()
    SITE_CACHE = LocalSyncCache(id="DynamicSiteMiddlewareCache")
    sites_models.SITE_CACHE = SITE_CACHE

    SITE_THREAD_LOCAL = local()

    # Use Fallback ID if host not exist in Site table. We use int() here, because
    # os environment variables are always strings.
    FALLBACK_SITE_ID = int(getattr(os.environ, "SITE_ID", settings.SITE_ID))
    logger.debug("Fallback SITE_ID: %r" % FALLBACK_SITE_ID)

    # Use Fallback ID at startup before process_request(), e.g. in unittests
    SITE_THREAD_LOCAL.SITE_ID = FALLBACK_SITE_ID

    try:
        FALLBACK_SITE = Site.objects.get(id=FALLBACK_SITE_ID)
    except Site.DoesNotExist as e:
    def testLocalSyncCacheMiddleware(self):
        middleware = LocalSyncCacheMiddleware()

        c1 = LocalSyncCache(id="testLocalSyncCacheMiddleware1")
        c2 = LocalSyncCache(id="testLocalSyncCacheMiddleware1", unique_ids=False)

        c3 = LocalSyncCache(id="testLocalSyncCacheMiddleware2")

        self.assertEqual(len(LocalSyncCache.CACHES), 3)

        c1["c1"] = "foo"
        c2["c2"] = "bar"
        c3["foo"] = "bar"

        middleware.process_request(None)

        self.assertEqual(c1, {'c1': 'foo'})
        self.assertEqual(c2, {'c2': 'bar'})
        self.assertEqual(c3, {'foo': 'bar'})

        c1.clear()
        self.assertEqual(c1, {})

        # In a "new request" all the same caches should be cleared
        middleware.process_request(None)
        self.assertEqual(c2, {})

        # Other caches should be not affected by clear()
        self.assertEqual(c3, {'foo': 'bar'})

        c1["c1"] = "foo2"
        c2["c2"] = "bar2"

        middleware.process_request(None)

        self.assertEqual(c1, {'c1': 'foo2'})
        self.assertEqual(c2, {'c2': 'bar2'})
        self.assertEqual(c3, {'foo': 'bar'})

        c2.clear()
        self.assertEqual(c2, {})

        # In a "new request" all the same caches should be cleared
        middleware.process_request(None)
        self.assertEqual(c1, {})

#        print LocalSyncCache.pformat_cache_information()
        cache_information = LocalSyncCache.get_cache_information()
        self.assertEqual(len(cache_information), 3)
        for item in cache_information:
            instance = item["instance"]
            self.assertEqual(instance.request_counter, 4)

            if instance.id == "testLocalSyncCacheMiddleware2":
                self.assertEqual(instance.own_clear_counter, 0)
                self.assertEqual(instance.ext_clear_counter, 0)
                self.assertEqual(instance, {'foo': 'bar'})
            else:
                self.assertEqual(instance.own_clear_counter, 1)
                self.assertEqual(instance.ext_clear_counter, 1)
                self.assertEqual(instance, {})
 def testPformatCacheInfo(self):
     LocalSyncCache(id="FooBar")
     txt = LocalSyncCache.pformat_cache_information()
     self.assertTrue("id: FooBar" in txt)
     self.assertTrue("instance: {}" in txt)
     self.assertTrue("cleared: False" in txt)
Example #24
0
class PageTree(BaseModel, BaseTreeModel, UpdateInfoBaseModel, PermissionsBase):
    """
    The CMS page tree

    inherited attributes from TreeBaseModel:
        parent
        position

    inherited attributes from UpdateInfoBaseModel:
        createtime     -> datetime of creation
        lastupdatetime -> datetime of the last change
        createby       -> ForeignKey to user who creaded this entry
        lastupdateby   -> ForeignKey to user who has edited this entry
        
    inherited from PermissionsBase:
        validate_permit_group()
        check_sub_page_permissions()
    """
    PAGE_TYPE = 'C'
    PLUGIN_TYPE = 'P'

    TYPE_CHOICES = (
        (PAGE_TYPE, 'CMS-Page'),
        (PLUGIN_TYPE, 'PluginPage'),
    )
    TYPE_DICT = dict(TYPE_CHOICES)

    objects = PageTreeManager()

    slug = models.SlugField(unique=False, help_text="(for building URLs)")

    site = models.ForeignKey(Site, default=Site.objects.get_current)
    on_site = CurrentSiteManager()

    page_type = models.CharField(max_length=1, choices=TYPE_CHOICES)

    design = models.ForeignKey("pylucid.Design",
                               help_text="Page Template, CSS/JS files")

    showlinks = models.BooleanField(
        default=True,
        help_text=
        "Accessable for all users, but don't put a Link to this page into menu/sitemap etc."
    )
    permitViewGroup = models.ForeignKey(
        Group,
        related_name="%(class)s_permitViewGroup",
        help_text="Limit viewable to a group?",
        null=True,
        blank=True,
    )
    permitEditGroup = models.ForeignKey(
        Group,
        related_name="%(class)s_permitEditGroup",
        help_text="Usergroup how can edit this page.",
        null=True,
        blank=True,
    )

    def clean_fields(self, exclude):
        """
        We must call clean_slug() here, because it needs a queryset. 
        """
        # check if parent is the same entry: child <-> parent loop:
        super(PageTree, self).clean_fields(exclude)

        message_dict = {}

        # Check if slug exist in the same sub tree:
        if "slug" not in exclude:
            if self.parent == None:  # parent is the tree root
                if self.slug in settings.SLUG_BLACKLIST:
                    # e.g. /media/ or /pylucid_admin/
                    msg = (
                        "Sorry, page slug '/<strong>%s</strong>/' is not usable!"
                        " (Not usable slugs are: %s)") % (self.slug, ", ".join(
                            settings.SLUG_BLACKLIST))
                    message_dict["slug"] = (mark_safe(msg), )

            queryset = PageTree.on_site.filter(slug=self.slug,
                                               parent=self.parent)

            # Exclude the current object from the query if we are editing an
            # instance (as opposed to creating a new one)
            if self.pk is not None:
                queryset = queryset.exclude(pk=self.pk)

            exists = queryset.count()
            if exists:
                if self.parent == None:  # parent is the tree root
                    parent_url = "/"
                else:
                    parent_url = self.parent.get_absolute_url()

                msg = "Page '%s<strong>%s</strong>/' exists already." % (
                    parent_url, self.slug)
                message_dict["slug"] = (mark_safe(msg), )

        # Check if parent page is a ContentPage, a plugin page can't have any sub pages!
        if "parent" not in exclude and self.parent is not None and self.parent.page_type != self.PAGE_TYPE:
            parent_url = self.parent.get_absolute_url()
            msg = _(
                "Can't use the <strong>plugin</strong> page '%s' as parent page!"
                " Please choose a <strong>content</strong> page.") % parent_url
            message_dict["parent"] = (mark_safe(msg), )

        # Prevents that a unprotected page created below a protected page.
        # TODO: Check this in unittests
        # validate_permit_group() method inherited from PermissionsBase
        self.validate_permit_group("permitViewGroup", exclude, message_dict)
        self.validate_permit_group("permitEditGroup", exclude, message_dict)

        # Warn user if PageTree permissions mismatch with sub pages
        # TODO: Check this in unittests
        queryset = PageTree.objects.filter(parent=self)
        self.check_sub_page_permissions(  # method inherited from PermissionsBase
            ("permitViewGroup", "permitEditGroup"), exclude, message_dict,
            queryset)

        if message_dict:
            raise ValidationError(message_dict)

    def recusive_attribute(self, attribute):
        """
        Goes the pagetree back to root and return the first match of attribute if not None.
        
        used e.g.
            with permitViewGroup and permitEditGroup
            from self.validate_permit_group() and self.check_sub_page_permissions()
        """
        parent = self.parent
        if parent is None:  # parent is the tree root
            return None

        if getattr(parent, attribute) is not None:
            # the attribute was set by parent page
            return parent
        else:
            # go down to root
            return parent.recusive_attribute(attribute)

    _url_cache = LocalSyncCache(id="PageTree_absolute_url")

    def get_absolute_url(self):
        """ absolute url *without* language code (without domain/host part) """
        try:
            url = self._url_cache[self.pk]
            # print "PageTree url cache len: %s, pk: %s" % (len(self._url_cache), self.pk)
        except KeyError:
            if self.parent:
                parent_shortcut = self.parent.get_absolute_url()
                url = parent_shortcut + self.slug + "/"
            else:
                url = "/" + self.slug + "/"

            self._url_cache[self.pk] = url
        return url

    def get_absolute_uri(self):
        """ absolute url with domain/host part (but without language code) """
        absolute_url = self.get_absolute_url()
        domain = self.site.domain
        return "http://" + domain + absolute_url

    def save(self, *args, **kwargs):
        """ reset PageMeta and PageTree url cache """
        from pagemeta import PageMeta  # against import loops.

        # Clean the local url cache dict
        self._url_cache.clear()
        PageMeta._url_cache.clear()

        # FIXME: We must only update the cache for the current SITE not for all sites.
        try:
            cache.smooth_update(
            )  # Save "last change" timestamp in django-tools SmoothCacheBackend
        except AttributeError:
            # No SmoothCacheBackend used -> clean the complete cache
            cache.clear()

        return super(PageTree, self).save(*args, **kwargs)

    def get_site(self):
        """ used e.g. for self.get_absolute_uri() and the admin page """
        return self.site

    def __unicode__(self):
        return u"PageTree %r (id: %i, site: %s, type: %s)" % (
            self.slug, self.id, self.site.domain,
            self.TYPE_DICT.get(self.page_type))

    class Meta:
        app_label = 'pylucid'
        verbose_name_plural = verbose_name = "PageTree"
        unique_together = (("site", "slug", "parent"), )

        # FIXME: It would be great if we can order by get_absolute_url()
        #        ordering = ("site", "id", "position")
        ordering = ("-lastupdatetime", )