[View Cache] [Delete from Cache] -
Backend: {{ cache_backend }} ({% if cache_running %}running{% else %}down{% endif %})
-Timeout: {{ cache_time }}
-Keys in cache: {{ cache_count }}
-Cache Calls: {{ cache_calls }}
-Cache Hits: {{ cache_hits }}
-Cache Hit Rate: {{ hit_rate }}%
-{% endblock %} diff --git a/keyedcache/templates/keyedcache/view.html b/keyedcache/templates/keyedcache/view.html deleted file mode 100644 index 3034a98f..00000000 --- a/keyedcache/templates/keyedcache/view.html +++ /dev/null @@ -1,17 +0,0 @@ -{% extends "admin/base_site.html" %} -{% load i18n %} - -{% block breadcrumbs %}{% if not is_popup %} - -{% endif %}{% endblock %} - -{% block content %} -[Cache Stats] [Delete from Cache] -
{% for key in cached_keys %}{{ key }}, {% endfor %} -
-{% endblock %} diff --git a/keyedcache/tests.py b/keyedcache/tests.py deleted file mode 100644 index 8abb8dd3..00000000 --- a/keyedcache/tests.py +++ /dev/null @@ -1,150 +0,0 @@ -import keyedcache -import random -from django.test import TestCase -import time - -CACHE_HIT=0 - -def cachetest(a,b,c): - global CACHE_HIT - CACHE_HIT += 1 - r = [random.randrange(0,1000) for x in range(0,3)] - ret = [r, a + r[0], b + r[1], c + r[2]] - return ret - -cachetest = keyedcache.cache_function(2)(cachetest) - -class DecoratorTest(TestCase): - - def testCachePut(self): - d = cachetest(1,2,3) - self.assertEqual(CACHE_HIT,1) - - d2 = cachetest(1,2,3) - self.assertEqual(CACHE_HIT,1) - self.assertEqual(d, d2) - - seeds = d[0] - self.assertEqual(seeds[0] + 1, d[1]) - self.assertEqual(seeds[1] + 2, d[2]) - self.assertEqual(seeds[2] + 3, d[3]) - - time.sleep(3) - d3 = cachetest(1,2,3) - self.assertEqual(CACHE_HIT,2) - self.assertNotEqual(d, d3) - - def testDeleteCachedFunction(self): - orig = cachetest(10,20,30) - keyedcache.cache_delete_function(cachetest) - after = cachetest(10,20,30) - self.assertNotEqual(orig,keyedcache) - -class CachingTest(TestCase): - - def testCacheGetFail(self): - try: - keyedcache.cache_get('x') - self.fail('should have raised NotCachedError') - except keyedcache.NotCachedError: - pass - - def testCacheGetOK(self): - one = [1,2,3,4] - keyedcache.cache_set('ok', value=one, length=2) - two = keyedcache.cache_get('ok') - self.assertEqual(one, two) - - time.sleep(5) - try: - three = keyedcache.cache_get('ok') - self.fail('should have raised NotCachedError, got %s' % three) - except keyedcache.NotCachedError: - pass - - def testCacheGetDefault(self): - chk = keyedcache.cache_get('default',default='-') - self.assertEqual(chk, '-') - - - def testDelete(self): - keyedcache.cache_set('del', value=True) - - for x in range(0,10): - keyedcache.cache_set('del', 'x', x, value=True) - for y in range(0,5): - keyedcache.cache_set('del', 'x', x, 'y', y, value=True) - - # check to make sure all the values are in the cache - self.assert_(keyedcache.cache_get('del', default=False)) - for x in range(0,10): - self.assert_(keyedcache.cache_get('del', 'x', x, default=False)) - for y in range(0,5): - self.assert_(keyedcache.cache_get('del', 'x', x, 'y', y, default=False)) - - # try to delete just one - killed = keyedcache.cache_delete('del','x',1) - self.assertEqual([keyedcache.CACHE_PREFIX + "::del::x::1"], killed) - self.assertFalse(keyedcache.cache_get('del', 'x', 1, default=False)) - - # but the others are still there - self.assert_(keyedcache.cache_get('del', 'x', 2, default=False)) - - # now kill all of del::x::1 - killed = keyedcache.cache_delete('del','x', 1, children=True) - for y in range(0,5): - self.assertFalse(keyedcache.cache_get('del', 'x', 1, 'y', y, default=False)) - - # but del::x::2 and children are there - self.assert_(keyedcache.cache_get('del','x',2,'y',1, default=False)) - - # kill the rest - killed = keyedcache.cache_delete('del', children=True) - self.assertFalse(keyedcache.cache_get('del',default=False)) - for x in range(0,10): - self.assertFalse(keyedcache.cache_get('del', 'x', x, default=False)) - for y in range(0,5): - self.assertFalse(keyedcache.cache_get('del', 'x', x, 'y', y, default=False)) - - -class TestCacheDisable(TestCase): - - def testDisable(self): - keyedcache.cache_set('disabled', value=False) - v = keyedcache.cache_get('disabled') - self.assertEqual(v, False) - - keyedcache.cache_enable(False) - keyedcache.cache_set('disabled', value=True) - try: - keyedcache.cache_get('disabled') - self.fail('should have raised NotCachedError') - except keyedcache.NotCachedError, nce: - key = keyedcache.cache_key('disabled') - self.assertEqual(nce.key, key) - - keyedcache.cache_enable() - v2 = keyedcache.cache_get('disabled') - # should still be False, since the cache was disabled - self.assertEqual(v2, False) - -class TestKeyMaker(TestCase): - - def testSimpleKey(self): - v = keyedcache.cache_key('test') - self.assertEqual(v, keyedcache.CACHE_PREFIX + '::test') - - def testDualKey(self): - v = keyedcache.cache_key('test', 2) - self.assertEqual(v, keyedcache.CACHE_PREFIX + '::test::2') - - def testPairedKey(self): - v = keyedcache.cache_key('test', more='yes') - self.assertEqual(v, keyedcache.CACHE_PREFIX + '::test::more::yes') - - def testPairedDualKey(self): - v = keyedcache.cache_key('test', 3, more='yes') - self.assertEqual(v, keyedcache.CACHE_PREFIX + '::test::3::more::yes') - - - diff --git a/keyedcache/threaded.py b/keyedcache/threaded.py deleted file mode 100644 index 997fddbc..00000000 --- a/keyedcache/threaded.py +++ /dev/null @@ -1,32 +0,0 @@ -"""Causes the keyedcache to also use a first-level cache in memory - this can cut 30-40% of memcached calls. - -To enable, add this to some models.py file in an app:: - - from keyedcache import threaded - threaded.start_listening() - -""" -from threaded_multihost import threadlocals -from django.core.signals import request_started, request_finished -from keyedcache import cache_clear_request, cache_use_request_caching -import random -import logging -log = logging.getLogger('keyedcache.threaded') - -def set_request_uid(sender, *args, **kwargs): - """Puts a unique id into the thread""" - tid = random.randrange(1,10000000) - threadlocals.set_thread_variable('request_uid', tid) - #log.debug('request UID: %s', tid) - -def clear_request_uid(sender, *args, **kwargs): - """Removes the thread cache for this request""" - tid = threadlocals.get_thread_variable('request_uid', -1) - if tid > -1: - cache_clear_request(tid) - -def start_listening(): - log.debug('setting up threaded keyedcache') - cache_use_request_caching() - request_started.connect(set_request_uid) - request_finished.connect(clear_request_uid) diff --git a/keyedcache/urls.py b/keyedcache/urls.py deleted file mode 100644 index 1a944043..00000000 --- a/keyedcache/urls.py +++ /dev/null @@ -1,10 +0,0 @@ -""" -URLConf for Caching app -""" - -from django.conf.urls.defaults import patterns -urlpatterns = patterns('keyedcache.views', - (r'^$', 'stats_page', {}, 'keyedcache_stats'), - (r'^view/$', 'view_page', {}, 'keyedcache_view'), - (r'^delete/$', 'delete_page', {}, 'keyedcache_delete'), -) diff --git a/keyedcache/utils.py b/keyedcache/utils.py deleted file mode 100644 index 29b8fd71..00000000 --- a/keyedcache/utils.py +++ /dev/null @@ -1,14 +0,0 @@ -import types - -def is_string_like(maybe): - """Test value to see if it acts like a string""" - try: - maybe+"" - except TypeError: - return 0 - else: - return 1 - - -def is_list_or_tuple(maybe): - return isinstance(maybe, (types.TupleType, types.ListType)) diff --git a/keyedcache/views.py b/keyedcache/views.py deleted file mode 100644 index 9a3c1219..00000000 --- a/keyedcache/views.py +++ /dev/null @@ -1,103 +0,0 @@ -from django import forms -from django.conf import settings -from django.contrib.auth.decorators import user_passes_test -from django.http import HttpResponseRedirect -from django.shortcuts import render_to_response -from django.template import RequestContext -from django.utils.translation import ugettext_lazy as _ -import keyedcache -import logging - -log = logging.getLogger('keyedcache.views') - -YN = ( - ('Y', _('Yes')), - ('N', _('No')), - ) - -class CacheDeleteForm(forms.Form): - tag = forms.CharField(label=_('Key to delete'), required=False) - children = forms.ChoiceField(label=_('Include Children?'), choices=YN, initial="Y") - kill_all = forms.ChoiceField(label=_('Delete all keys?'), choices=YN, initial="Y") - - def delete_cache(self): - - data = self.cleaned_data - if data['kill_all'] == "Y": - keyedcache.cache_delete() - result = "Deleted all keys" - elif data['tag']: - keyedcache.cache_delete(data['tag'], children=data['children']) - if data['children'] == "Y": - result = "Deleted %s and children" % data['tag'] - else: - result = "Deleted %s" % data['tag'] - else: - result = "Nothing selected to delete" - - log.debug(result) - return result - -def stats_page(request): - calls = keyedcache.CACHE_CALLS - hits = keyedcache.CACHE_HITS - - if (calls and hits): - rate = float(keyedcache.CACHE_HITS)/keyedcache.CACHE_CALLS*100 - else: - rate = 0 - - try: - running = keyedcache.cache_require() - - except keyedcache.CacheNotRespondingError: - running = False - - ctx = RequestContext(request, { - 'cache_count' : len(keyedcache.CACHED_KEYS), - 'cache_running' : running, - 'cache_time' : settings.CACHE_TIMEOUT, - 'cache_backend' : settings.CACHE_BACKEND, - 'cache_calls' : keyedcache.CACHE_CALLS, - 'cache_hits' : keyedcache.CACHE_HITS, - 'hit_rate' : "%02.1f" % rate - }) - - return render_to_response('keyedcache/stats.html', context_instance=ctx) - -stats_page = user_passes_test(lambda u: u.is_authenticated() and u.is_staff, login_url='/accounts/login/')(stats_page) - -def view_page(request): - keys = keyedcache.CACHED_KEYS.keys() - - keys.sort() - - ctx = RequestContext(request, { - 'cached_keys' : keys, - }) - - return render_to_response('keyedcache/view.html', context_instance=ctx) - -view_page = user_passes_test(lambda u: u.is_authenticated() and u.is_staff, login_url='/accounts/login/')(view_page) - -def delete_page(request): - log.debug("delete_page") - if request.method == "POST": - form = CacheDeleteForm(request.POST) - if form.is_valid(): - log.debug('delete form valid') - results = form.delete_cache() - return HttpResponseRedirect('../') - else: - log.debug("Errors in form: %s", form.errors) - else: - log.debug("new form") - form = CacheDeleteForm() - - ctx = RequestContext(request, { - 'form' : form, - }) - - return render_to_response('keyedcache/delete.html', context_instance=ctx) - -delete_page = user_passes_test(lambda u: u.is_authenticated() and u.is_staff, login_url='/accounts/login/')(delete_page) diff --git a/settings.py b/settings.py deleted file mode 100644 index 63d29c4f..00000000 --- a/settings.py +++ /dev/null @@ -1,98 +0,0 @@ -# encoding:utf-8 -# Django settings for lanai project. -import os.path -import sys - -SITE_ID = 1 - -ADMIN_MEDIA_PREFIX = '/admin/media/' -SECRET_KEY = '$oo^&_m&qwbib=(_4m_n*zn-d=g#s0he5fx9xonnym#8p6yigm' -# List of callables that know how to import templates from various sources. -TEMPLATE_LOADERS = ( - 'django.template.loaders.filesystem.load_template_source', - 'django.template.loaders.app_directories.load_template_source', - - #below is askbot stuff for this tuple - 'askbot.skins.loaders.load_template_source',#askbot stuff -# 'django.template.loaders.eggs.load_template_source', -) - -MIDDLEWARE_CLASSES = ( - #'django.middleware.gzip.GZipMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - #'django.middleware.locale.LocaleMiddleware', - #'django.middleware.cache.UpdateCacheMiddleware', - 'django.middleware.common.CommonMiddleware', - #'django.middleware.cache.FetchFromCacheMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - #'django.middleware.sqlprint.SqlPrintingMiddleware', - - #below is askbot stuff for this tuple - 'askbot.middleware.anon_user.ConnectToSessionMessagesMiddleware', - 'askbot.middleware.pagesize.QuestionsPageSizeMiddleware', - 'askbot.middleware.cancel.CancelActionMiddleware', - #'recaptcha_django.middleware.ReCaptchaMiddleware', - 'django.middleware.transaction.TransactionMiddleware', - 'debug_toolbar.middleware.DebugToolbarMiddleware', - 'askbot.middleware.view_log.ViewLogMiddleware', - 'askbot.middleware.spaceless.SpacelessMiddleware', -) - -#all of these are necessary for the askbot and absend in default settings.py -TEMPLATE_CONTEXT_PROCESSORS = ( - 'django.core.context_processors.request', - 'askbot.context.application_settings', - #'django.core.context_processors.i18n', - 'askbot.user_messages.context_processors.user_messages',#must be before auth - 'django.core.context_processors.auth', #this is required for admin -) - -ROOT_URLCONF = 'urls' - -TEMPLATE_DIRS = ( - #specific to askbot - os.path.join(os.path.dirname(__file__),'askbot','skins').replace('\\','/'), -) - -#UPLOAD SETTINGS -FILE_UPLOAD_TEMP_DIR = os.path.join(os.path.dirname(__file__), 'tmp').replace('\\','/') -FILE_UPLOAD_HANDLERS = ("django.core.files.uploadhandler.MemoryFileUploadHandler", - "django.core.files.uploadhandler.TemporaryFileUploadHandler",) -DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage' - -# User settings -from settings_local import * - -INSTALLED_APPS = ( - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.sites', - - #all of these are needed for the askbot - 'django.contrib.admin', - 'django.contrib.humanize', - 'django.contrib.sitemaps', - 'debug_toolbar', - 'askbot', - 'askbot.deps.django_authopenid', - #'askbot.importers.stackexchange', #se loader - 'south', - 'askbot.deps.livesettings', - 'keyedcache', -) - -AUTHENTICATION_BACKENDS = ('django.contrib.auth.backends.ModelBackend',) - -#this needs to go -if 'USE_EXTERNAL_LEGACY_LOGIN' in locals() and USE_EXTERNAL_LEGACY_LOGIN: - INSTALLED_APPS += (EXTERNAL_LEGACY_LOGIN_MODULE,) - - if 'EXTERNAL_LEGACY_LOGIN_AUTHENTICATION_BACKEND' in locals(): - AUTHENTICATION_BACKENDS += (EXTERNAL_LEGACY_LOGIN_AUTHENTICATION_BACKEND,) - if 'EXTERNAL_LEGACY_LOGIN_AUTHENTICATION_MIDDLEWARE' in locals(): - MIDDLEWARE_CLASSES += (EXTERNAL_LEGACY_LOGIN_AUTHENTICATION_MIDDLEWARE,) - def LOAD_EXTERNAL_LOGIN_APP(): - return __import__(EXTERNAL_LEGACY_LOGIN_MODULE, [], [], ['api','forms','views']) -else: - LOAD_EXTERNAL_LOGIN_APP = lambda: None diff --git a/settings_local.py.dist b/settings_local.py.dist deleted file mode 100755 index d6f537fb..00000000 --- a/settings_local.py.dist +++ /dev/null @@ -1,105 +0,0 @@ -# encoding:utf-8 -import os.path -from django.utils.translation import ugettext as _ - -SITE_SRC_ROOT = os.path.dirname(__file__) -LOG_FILENAME = 'askbot.log' - -#for logging -import logging -logging.basicConfig( - filename=os.path.join(SITE_SRC_ROOT, 'log', LOG_FILENAME), - level=logging.DEBUG, - format='%(pathname)s TIME: %(asctime)s MSG: %(filename)s:%(funcName)s:%(lineno)d %(message)s', -) - -#ADMINS and MANAGERS -ADMINS = (('Forum Admin', 'forum@example.com'),) -MANAGERS = ADMINS - -#DEBUG SETTINGS -DEBUG = False -TEMPLATE_DEBUG = DEBUG -INTERNAL_IPS = ('127.0.0.1',) - -DATABASE_NAME = '' # Or path to database file if using sqlite3. -DATABASE_USER = '' # Not used with sqlite3. -DATABASE_PASSWORD = '' # Not used with sqlite3. -DATABASE_ENGINE = '' #mysql, etc -DATABASE_HOST = '' -DATABASE_PORT = '' - -#setup memcached for production use! -#see http://docs.djangoproject.com/en/1.1/topics/cache/ for details -CACHE_BACKEND = 'locmem://' - -#If you use memcache you may want to uncomment the following line to enable memcached based sessions -#SESSION_ENGINE = 'django.contrib.sessions.backends.cache_db' -# for user upload - -ALLOW_FILE_TYPES = ('.jpg', '.jpeg', '.gif', '.bmp', '.png', '.tiff') -# unit byte -ALLOW_MAX_FILE_SIZE = 1024 * 1024 - -#email server settings -SERVER_EMAIL = '' -DEFAULT_FROM_EMAIL = '' -EMAIL_HOST_USER = '' -EMAIL_HOST_PASSWORD = '' -EMAIL_SUBJECT_PREFIX = '[ASKBOT] ' -EMAIL_HOST='askbot.org' -EMAIL_PORT='25' -EMAIL_USE_TLS=False - -#HACK - anonymous user email - for email-less users -ANONYMOUS_USER_EMAIL = 'anonymous@askbot.org' - -#LOCALIZATIONS -TIME_ZONE = 'America/New_York' - -########################### -# -# this will allow running your forum with url like http://site.com/forum -# -# FORUM_SCRIPT_ALIAS = 'forum/' -# -FORUM_SCRIPT_ALIAS = '' #no leading slash, default = '' empty string - - -#OTHER SETTINGS -APP_TITLE = u'ASKBOT: Open Source Q&A Forum' -APP_SHORT_NAME = u'ASKBOT' -APP_KEYWORDS = u'ASKBOT,CNPROG,forum,community' -APP_DESCRIPTION = u'Ask and answer questions.' -APP_INTRO = u'Ask and answer questions, make the world better!
' -APP_COPYRIGHT = 'Copyright ASKBOT, 2009. Some rights reserved under creative commons license.' -LOGIN_URL = '/%s%s%s' % (FORUM_SCRIPT_ALIAS,'account/','signin/') -GREETING_URL = LOGIN_URL #may be url of "faq" page or "about", etc - -USE_I18N = True -LANGUAGE_CODE = 'en' -EMAIL_VALIDATION = 'off' #string - on|off -MIN_USERNAME_LENGTH = 1 -EMAIL_UNIQUE = False -APP_URL = 'http://askbot.org' #used by email notif system and RSS -GOOGLE_SITEMAP_CODE = '' -GOOGLE_ANALYTICS_KEY = '' -WIKI_ON = True -FEEDBACK_SITE_URL = None #None or url -EDITABLE_SCREEN_NAME = False #True or False - can user change screen name? - -DJANGO_VERSION = 1.1 -RESOURCE_REVISION=4 - -#please get these at recaptcha.net -RECAPTCHA_PRIVATE_KEY='...' -RECAPTCHA_PUBLIC_KEY='...' -ASKBOT_DEFAULT_SKIN = 'default' - - -#Facebook settings -USE_FB_CONNECT=False -FB_API_KEY='' #your api key from facebook -FB_SECRET='' #your application secret - -USE_EXTERNAL_LEGACY_LOGIN = False #DO NOT USE, and do not delete this line, will be removed later diff --git a/setup.py b/setup.py new file mode 100644 index 00000000..1a40d4c4 --- /dev/null +++ b/setup.py @@ -0,0 +1,30 @@ +import ez_setup +ez_setup.use_setuptools() +from setuptools import setup, find_packages + +setup( + name = "askbot", + version = "0.6.0", + packages = find_packages(), + author = 'Evgeny.Fadeev', + author_email = 'evgeny.fadeev@gmail.com', + license = 'GPLv3', + keywords = 'forum, community, wiki, Q&A', + url = 'http://askbot.org', + include_package_data = True, + install_requires = [ + 'django==1.1.2', + 'django-debug-toolbar==0.7.0', + 'South', + 'recaptcha-client', + 'markdown2', + 'html5lib', + 'python-openid', + 'django-keyedcache', + 'mysql-python', + ], + long_description = """Open Source Question and Answer forum. + Based on CNPROG project by Mike Chen and Sailing Cai, project + is inspired by StackOverflow. + """, +)