Commits

David Chambers committed 501b247

Replaced `from mango.settings` imports with `import mango.settings` to enable
scripts (such as the update script) to alter settings at runtime if necessary.

  • Participants
  • Parent commits 3bdf019

Comments (0)

Files changed (14)

extras/blogger.py

     sys.exit(1)
 
 from settings import TIME_ZONE
-from mango.settings import (BODY_WIDTH, DOCUMENTS_PATH,
-        MARKDOWN_DATE_FORMAT, MARKDOWN_TIME_FORMAT)
+import mango.settings
 from mango.utils import lstrip, posts_directory
 
 TZ_OFFSET = re.compile(r'(?P<sign>[+-])(?P<hours>\d\d):?(?P<minutes>\d\d)$')
 
     dt = datetime.strptime(timestamp[:19], '%Y-%m-%dT%H:%M:%S')
     dt = dt.replace(tzinfo=TZ(offset)).astimezone(pytz.timezone(TIME_ZONE))
-    lines.append(u'date: %s' % lstrip(dt.strftime(MARKDOWN_DATE_FORMAT)))
-    lines.append(u'time: %s' % lstrip(dt.strftime(MARKDOWN_TIME_FORMAT)).lower())
+    lines.append(u'date: %s' % lstrip(dt.strftime(mango.settings.MARKDOWN_DATE_FORMAT)))
+    lines.append(u'time: %s' % lstrip(dt.strftime(mango.settings.MARKDOWN_TIME_FORMAT)).lower())
     lines.append(u'zone: %s' % TIME_ZONE)
     lines.append(u'author: %s' % entry['author'][0]['name']['$t'])
 
     content = re.sub(BLOGGER_POST_FOOTER, '', content)
 
     # convert HTML to Markdown
-    html2text.BODY_WIDTH = BODY_WIDTH
+    html2text.BODY_WIDTH = mango.settings.BODY_WIDTH
     content = html2text.html2text(content).strip()
 
     lines.append(content)
         slug = re.sub(r'[^a-z0-9_-]', '', title.lower())
         slug = re.sub(r'\s+', '-', slug)
 
-    with open(os.path.join(DOCUMENTS_PATH, '%s.text' % slug), 'w') as f:
+    with open(os.path.join(mango.settings.DOCUMENTS_PATH, '%s.text' % slug), 'w') as f:
         f.write(u'%s\n' % '\n'.join(lines))
 
 sys.stdout.write('Successfully imported %s %s.\n' % (
     sys.stderr.write('Failed to locate Mango.\n')
     sys.exit(1)
 
-from mango.settings import PROJECT_PATH
-head, tail = os.path.split(PROJECT_PATH)
+import mango.settings
+head, tail = os.path.split(mango.settings.PROJECT_PATH)
 sys.path.append(head)
 os.environ['DJANGO_SETTINGS_MODULE'] = '%s.settings' % tail
 
-from mango.settings import MANGO_PATH, REPO_URL
-repo = hg.repository(ui=ui.ui(), path=MANGO_PATH)
+repo = hg.repository(ui=ui.ui(), path=mango.settings.MANGO_PATH)
 old_tip = repo['tip']
-commands.pull(ui=ui.ui(), repo=repo, source=REPO_URL, update=True)
+commands.pull(ui=ui.ui(), repo=repo, source=mango.settings.REPO_URL, update=True)
 new_tip = repo['tip']
 
 if new_tip == old_tip:
     sys.stdout.write('You are already running the latest version of Mango.\n')
     sys.exit()
 
-import mango
+reload(mango.settings) # `mango.settings` has already been imported and is now stale
+
 from mango.main import Index
 
 # clear documents from the cache
 
 Index.get()
 
+import mango
 sys.stdout.write('Successfully updated to Mango %s (%s).\n' % (mango.VERSION, new_tip))
 sys.exit()
     sys.exit(1)
 
 from settings import TIME_ZONE
-from mango.settings import (BODY_WIDTH, DOCUMENTS_PATH,
-        MARKDOWN_DATE_FORMAT, MARKDOWN_TIME_FORMAT)
+import mango.settings
 from mango.utils import lstrip, posts_directory, unescape
 
 # assign arguments to variables
 pages = server.wp.getPages(blog_id, username, password)
 
 for page in pages:
-    html2text.BODY_WIDTH = BODY_WIDTH
-    with open(os.path.join(DOCUMENTS_PATH, '%s.text' % page['wp_slug']), 'w') as f:
+    html2text.BODY_WIDTH = mango.settings.BODY_WIDTH
+    with open(os.path.join(mango.settings.DOCUMENTS_PATH, '%s.text' % page['wp_slug']), 'w') as f:
         f.write(u'author: %s\n\n\n%s\n%s\n\n%s\n' % (
                 page['wp_author_display_name'],
                 page['title'], '=' * len(page['title']),
 
     dt = datetime.strptime(post['date_created_gmt'].value, '%Y%m%dT%H:%M:%S')
     dt = dt.replace(tzinfo=pytz.utc).astimezone(pytz.timezone(TIME_ZONE))
-    lines.append(u'date: %s' % lstrip(dt.strftime(MARKDOWN_DATE_FORMAT)))
-    lines.append(u'time: %s' % lstrip(dt.strftime(MARKDOWN_TIME_FORMAT)).lower())
+    lines.append(u'date: %s' % lstrip(dt.strftime(mango.settings.MARKDOWN_DATE_FORMAT)))
+    lines.append(u'time: %s' % lstrip(dt.strftime(mango.settings.MARKDOWN_TIME_FORMAT)).lower())
     lines.append(u'zone: %s' % TIME_ZONE)
     lines.append(u'author: %s' % post['wp_author_display_name'])
 
 
     if post['mt_excerpt']: # hand-crafted excerpt
         lines += ['', '']
-        html2text.BODY_WIDTH = BODY_WIDTH - 2
+        html2text.BODY_WIDTH = mango.settings.BODY_WIDTH - 2
         for line in html2text.html2text(post['mt_excerpt']).strip().splitlines():
             lines.append(u'| %s' % line)
 
     lines += ['', '', post['title'], '=' * len(post['title']), '']
 
-    html2text.BODY_WIDTH = BODY_WIDTH
+    html2text.BODY_WIDTH = mango.settings.BODY_WIDTH
     lines.append(html2text.html2text(post['description']).strip())
 
     if post['mt_text_more']: # <!--more-->
         lines.append('')
-        html2text.BODY_WIDTH = BODY_WIDTH - 2
+        html2text.BODY_WIDTH = mango.settings.BODY_WIDTH - 2
         for line in html2text.html2text(post['mt_text_more']).strip().splitlines():
             lines.append(u'| %s' % line)
 
-    with open(os.path.join(DOCUMENTS_PATH, '%s.text' % post['wp_slug']), 'w') as f:
+    with open(os.path.join(mango.settings.DOCUMENTS_PATH, '%s.text' % post['wp_slug']), 'w') as f:
         f.write(u'%s\n' % '\n'.join(lines))
 
 sys.stdout.write('Successfully imported %s %s and %s %s.\n' % (
 from django.core.cache import cache
 from django.utils import feedgenerator
 
+import mango.settings
 from mango.decorators import baseurl
 from mango.main import Index
-from mango.settings import (FEED_MAX_POSTS,
-        INDEX_CACHE_SECONDS, PRIMARY_AUTHOR_EMAIL,
-        PRIMARY_AUTHOR_NAME, PRIMARY_AUTHOR_URL, SITE_TITLE)
 
 @baseurl
 def atom(request, tag=None):
         return kwargs
 
     required = {
-        'title':        lambda: SITE_TITLE,
+        'title':        lambda: mango.settings.SITE_TITLE,
         'link':         lambda: baseurl(),
         'description':  lambda: u'', # required by constructor, but does not affect output
     }
     optional = {
-        'author_name':  lambda: PRIMARY_AUTHOR_NAME,
-        'author_email': lambda: PRIMARY_AUTHOR_EMAIL,
-        'author_link':  lambda: PRIMARY_AUTHOR_URL,
+        'author_name':  lambda: mango.settings.PRIMARY_AUTHOR_NAME,
+        'author_email': lambda: mango.settings.PRIMARY_AUTHOR_EMAIL,
+        'author_link':  lambda: mango.settings.PRIMARY_AUTHOR_URL,
         'feed_url':     lambda: feed_url,
         'feed_guid':    lambda: baseurl(),
     }
         return http.HttpResponseServerError
 
     feed = feedgenerator.Atom1Feed(**kwargs)
-    todo = FEED_MAX_POSTS
+    todo = mango.settings.FEED_MAX_POSTS
     all = todo == 0
 
     for post in Index.get().descendants():
                 todo -= 1
 
     xml = feed.writeString('utf-8')
-    cache.set(cache_key, xml, INDEX_CACHE_SECONDS)
+    cache.set(cache_key, xml, mango.settings.INDEX_CACHE_SECONDS)
     return http.HttpResponse(xml, content_type=content_type)
 
 from django import forms
 
+import mango.settings
 from mango.decorators import baseurl
-from mango.settings import AKISMET_API_KEY
 from mango.utils import akismet_request
 
 
         return self.cleaned_data.get('message', '').strip().replace('\r\n', '\n')
 
     def clean(self):
-        if AKISMET_API_KEY and self.is_valid():
+        if mango.settings.AKISMET_API_KEY and self.is_valid():
             args = {
                 'blog': baseurl(),
                 'user_ip': self.request.META['REMOTE_ADDR'],
 from django.shortcuts import get_object_or_404
 from django.template import Context, loader
 
+import mango.settings
 from mango.decorators import baseurl
 from mango.main import Index
-from mango.settings import (AKISMET_API_KEY, COMMENTS_REQUIRE_APPROVAL,
-        DISQUS, DISQUS_API_KEY, FORUM, SUBSCRIPTIONS)
 from mango.utils import akismet_request, logger, text_response
-if SUBSCRIPTIONS:
+if mango.settings.SUBSCRIPTIONS:
     from mango.models import Subscription
 
 @baseurl
 
 @baseurl
 def moderate(request, action):
-    if not DISQUS:
+    if not mango.settings.DISQUS:
         return text_response('Invalid DISQUS settings.', 500)
 
-    if request.GET.get('api_key') != hashlib.sha1(DISQUS_API_KEY).hexdigest():
+    if request.GET.get('api_key') != hashlib.sha1(mango.settings.DISQUS_API_KEY).hexdigest():
         return text_response('Invalid API key.', 400)
 
     post_id = request.GET.get('post_id')
     thread_id = request.GET.get('thread_id')
 
     if thread_id:
-        if not FORUM:
+        if not mango.settings.FORUM:
             return text_response('Invalid DISQUS settings.', 500)
 
-        for thread in DISQUS.get_thread_list(FORUM, limit=9999):
+        for thread in mango.settings.DISQUS.get_thread_list(mango.settings.FORUM, limit=9999):
             if thread.id == thread_id:
                 break
         else:
             return text_response('Invalid thread id.', 400)
 
     if action == 'close':
-        DISQUS.update_thread(FORUM, thread, allow_comments=False)
+        mango.settings.DISQUS.update_thread(mango.settings.FORUM, thread, allow_comments=False)
         message = 'Thread closed.'
 
     elif action == 'approve':
-        comment = DISQUS.moderate_post(post_id, 'approve')
+        comment = mango.settings.DISQUS.moderate_post(post_id, 'approve')
         message = 'Comment approved.'
         comment.thread.url = request.GET.get('url', comment.thread.url)
 
         cache.delete(cache_key)
         logger.debug('Cache key invalidated: %s' % cache_key)
 
-        if SUBSCRIPTIONS and comment.thread.url: # notify subscribers
+        if mango.settings.SUBSCRIPTIONS and comment.thread.url: # notify subscribers
             subject = u'New comment on "%s"' % comment.thread.title
             text_template = loader.get_template('email/subscriber.dtext')
             html_template = loader.get_template('email/subscriber.dhtml')
                 msg.attach_alternative(html_template.render(context), 'text/html')
                 msg.send(fail_silently=False)
     else:
-        comment = DISQUS.moderate_post(post_id, 'kill')
+        comment = mango.settings.DISQUS.moderate_post(post_id, 'kill')
         message = 'Comment deleted.'
 
-        if not COMMENTS_REQUIRE_APPROVAL:
+        if not mango.settings.COMMENTS_REQUIRE_APPROVAL:
             cache_key = 'mango:disqus:%s' % comment.thread.id
             cache.delete(cache_key)
             logger.debug('Cache key invalidated: %s' % cache_key)
 
         if action == 'spam':
-            DISQUS.moderate_post(post_id, 'spam')
+            mango.settings.DISQUS.moderate_post(post_id, 'spam')
             message = 'Comment marked as spam and deleted.'
 
-            if AKISMET_API_KEY and thread_id: # inform Akismet of its failure
-                for comment in DISQUS.get_thread_posts(FORUM, thread, limit=9999):
+            if mango.settings.AKISMET_API_KEY and thread_id: # inform Akismet of its failure
+                for comment in mango.settings.DISQUS.get_thread_posts(mango.settings.FORUM, thread, limit=9999):
                     if comment.id == post_id:
                         break
                 else:
 from django.utils.encoding import smart_str, smart_unicode
 from django.utils.safestring import mark_safe
 
-import mango
+import mango.settings
 from mango import decorators
-from mango.settings import (AUTHORS, COMMENTS_REQUIRE_APPROVAL, DISQUS,
-        DOCUMENTS_PATH, FORUM, INDEX_CACHE_SECONDS, KILOBYTE_SIZE,
-        MARKDOWN_DATE_FORMAT, MARKDOWN_EXTENSIONS, MARKDOWN_TIME_FORMAT,
-        POST_CACHE_SECONDS, PROJECT_PATH, SHORT_URL_BASE, STATIC_FILES,
-        TIME_ZONES)
 from mango.template import Script, StyleSheet
 from mango.templatetags.mango_extras import _convert, convert_html_chars
 from mango.utils import canonicalize, logger, replace, slugify
     'zone': re.compile(_meta % 'zone'),
 }
 
-md = markdown.Markdown(extensions=('meta',) + MARKDOWN_EXTENSIONS)
+md = markdown.Markdown(extensions=('meta',) + mango.settings.MARKDOWN_EXTENSIONS)
 update_template = loader.get_template('update.dhtml')
 youtube_template = loader.get_template('video/youtube.dhtml')
 
         canon_path = (u'%s%s/' % (mount_point, '/'.join(canon_fragments))).replace(*repl).lower()
         short_path = (u'%s%s/' % (mount_point, '/'.join(short_fragments))).replace(*repl).lower()
         self.urls = {
-            'canon': {'rel': canon_path, 'abs': u'%s%s' % (decorators.baseurl(), canon_path[1:])},
-            'short': {'rel': short_path, 'abs': u'%s%s' % (SHORT_URL_BASE or decorators.baseurl(), short_path[1:])},
+            'canon': {
+                'rel': canon_path,
+                'abs': u'%s%s' % (decorators.baseurl(), canon_path[1:]),
+            },
+            'short': {
+                'rel': short_path,
+                'abs': u'%s%s' % (mango.settings.SHORT_URL_BASE or decorators.baseurl(), short_path[1:]),
+            },
         }
 
         aliases = [u'']
         urlpaths = []
         for key in self.meta.get('require', []):
             try:
-                value = STATIC_FILES[key]
+                value = mango.settings.STATIC_FILES[key]
             except KeyError:
                 logger.warning('STATIC_FILES does not contain the key "%s"' % key)
             else:
 
     @classmethod
     def get(cls):
-        if INDEX_CACHE_SECONDS == 0:
+        if mango.settings.INDEX_CACHE_SECONDS == 0:
             return Index(use_cache=True)
 
         cache_key = Index.cache_key()
             return index
 
         index = Index(use_cache=True)
-        cache.set(cache_key, index, INDEX_CACHE_SECONDS)
+        cache.set(cache_key, index, mango.settings.INDEX_CACHE_SECONDS)
         logger.debug('Document tree created and cached')
         mango.sitemaps.ping_google()
         return index
 
     def __init__(self, use_cache=False):
-        super(Index, self).__init__(dirpath=DOCUMENTS_PATH, use_cache=use_cache)
+        super(Index, self).__init__(dirpath=mango.settings.DOCUMENTS_PATH, use_cache=use_cache)
 
     def uncache(self, uncache_documents=False):
         cache.delete(Index.cache_key())
 class Document(Resource):
     @classmethod
     def get(cls, filepath):
-        if POST_CACHE_SECONDS == 0:
+        if mango.settings.POST_CACHE_SECONDS == 0:
             return Document(filepath)
 
         cache_key = 'mango:%s' % filepath
         else:
             document = Document(filepath)
             document.lastmod = lastmod
-            cache.set(cache_key, document, POST_CACHE_SECONDS)
+            cache.set(cache_key, document, mango.settings.POST_CACHE_SECONDS)
             logger.debug('Document object created and cached: %s' % filepath)
 
         return document
             self._tags = [Tag(tag) for tag in self.meta['tags']]
 
         author_name = self.meta.get('author')
-        self.author = author_name and {'name': author_name, 'url': AUTHORS.get(author_name)} or None
+        self.author = author_name and {'name': author_name, 'url': mango.settings.AUTHORS.get(author_name)} or None
 
         self.datetime = None
         if 'date' in self.meta and 'time' in self.meta:
                         master._contents = contents
 
             if 'zone' in self.meta:
-                tz = pytz.timezone(smart_str(canonicalize(self.meta['zone'], TIME_ZONES)))
+                tz = pytz.timezone(smart_str(canonicalize(self.meta['zone'], mango.settings.TIME_ZONES)))
                 if self.meta['zone'] != tz.zone:
                     pattern = RE[self._apt('update_zone', 'zone')]
                     update_post(pattern, r'\2zone:\3%s\n' % tz.zone)
                 pattern = RE[self._apt('update_time', 'time')]
                 update_post(pattern, r'\1\2zone:\3%s\n' % tz.zone)
 
-            dt_format = u'%s %s' % (MARKDOWN_DATE_FORMAT, MARKDOWN_TIME_FORMAT)
+            dt_format = u'%s %s' % (
+                    mango.settings.MARKDOWN_DATE_FORMAT,
+                    mango.settings.MARKDOWN_TIME_FORMAT)
             try:
                 self.datetime = tz.localize(datetime.datetime.strptime('%s %s' % (
                         self.meta['date'], self.meta['time']), dt_format)).astimezone(pytz.utc)
 
         self.html = video_markup(self.html)
 
-        def filesize(filepath):
+        def filesize(filepath, kilobyte_size=mango.settings.KILOBYTE_SIZE):
             if not os.path.isabs(filepath):
-                filepath = os.path.join(PROJECT_PATH, filepath)
+                filepath = os.path.join(mango.settings.PROJECT_PATH, filepath)
             try:
                 filesize = os.path.getsize(filepath)
             except OSError:
 
             bytes = (
                 ('bytes', 1),
-                ('kB', KILOBYTE_SIZE**1),
-                ('MB', KILOBYTE_SIZE**2),
-                ('GB', KILOBYTE_SIZE**3),
-                ('TB', KILOBYTE_SIZE**4),
+                ('kB', kilobyte_size**1),
+                ('MB', kilobyte_size**2),
+                ('GB', kilobyte_size**3),
+                ('TB', kilobyte_size**4),
             )
             for unit, value in bytes:
-                if filesize <= value * KILOBYTE_SIZE or unit == 'TB':
+                if filesize <= value * kilobyte_size or unit == 'TB':
                     if unit == 'bytes':
                         return u'(%s\u2009bytes)' % filesize
                     else:
             self.type = self.meta.get('type', 'post' if self.datetime else 'page')
 
         # attach comments thread
-        if FORUM and hasattr(self, 'urls'):
+        if mango.settings.FORUM and hasattr(self, 'urls'):
             cache_key = 'mango:disqus:%s' % self.permalink()
             cached = cache.get(cache_key)
             if cached is not None:
             else:
                 try:
                     # accommodate old threads (Mango-made threads must be accessed by identifier)
-                    self._thread = (DISQUS.get_thread_by_url(FORUM, self.permalink())
-                                 or DISQUS.thread_by_identifier(FORUM, self.title, self.urls['canon']['rel'])['thread'])
+                    self._thread = (mango.settings.DISQUS.get_thread_by_url(mango.settings.FORUM, self.permalink())
+                                 or mango.settings.DISQUS.thread_by_identifier(mango.settings.FORUM, self.title, self.urls['canon']['rel'])['thread'])
                 except disqus.APIError, error:
                     logger.warning('Disqus API error: %s' % error)
                 else:
         comments = []
 
         try:
-            thread_posts = DISQUS.get_thread_posts(FORUM, self._thread, limit=9999, exclude='killed')
+            thread_posts = mango.settings.DISQUS.get_thread_posts(mango.settings.FORUM, self._thread, limit=9999, exclude='killed')
         except disqus.APIError, error:
             logger.warning('Disqus API error: %s' % error)
         else:
             for comment in thread_posts:
-                if comment.has_been_moderated or not COMMENTS_REQUIRE_APPROVAL:
+                if comment.has_been_moderated or not mango.settings.COMMENTS_REQUIRE_APPROVAL:
                     comment.html = replace(_convert(comment.message))
                     comments.append(comment)
             comments.sort(key=lambda comment: comment.created_at)
 from django.db import models
 
-from mango.settings import SUBSCRIPTIONS
+import mango.settings
 
-if SUBSCRIPTIONS: # since model requires a database, define it only if required
+if mango.settings.SUBSCRIPTIONS: # since model requires a database, define it only if required
     class Subscription(models.Model):
         subscriber_name = models.CharField(max_length=100)
         subscriber_email = models.EmailField(max_length=100)
 from django.contrib.sitemaps import PING_URL, Sitemap
 from django.core.urlresolvers import NoReverseMatch, reverse
 
+import mango.settings
 from mango.decorators import baseurl
 from mango.main import Index
-from mango.settings import SITEMAP
 from mango.utils import logger
 
 def ping_google(sitemap_url=None, ping_url=PING_URL):
-    if SITEMAP and not settings.DEBUG:
+    if mango.settings.SITEMAP and not settings.DEBUG:
         if sitemap_url is None:
             try:
                 sitemap_url = reverse('django.contrib.sitemaps.views.sitemap')

templatetags/mango_extras.py

 from django.utils.encoding import smart_unicode
 from django.utils.safestring import mark_safe
 
-from mango.settings import (AUTHORS, DISPLAY_DATE_FORMAT, DISPLAY_TIME_FORMAT,
-        GRAVATAR_DEFAULT_IMAGE_URL, GRAVATAR_IMAGE_SIZE, MARKDOWN_EXTENSIONS,
-        PRIMARY_AUTHOR_EMAIL, PRIMARY_AUTHOR_URL)
+import mango.settings
 
-md = markdown.Markdown(extensions=MARKDOWN_EXTENSIONS)
+md = markdown.Markdown(extensions=mango.settings.MARKDOWN_EXTENSIONS)
 
 register = template.Library()
 
 
 @register.filter
 def display_date(dt):
-    return display_date_or_time(dt, DISPLAY_DATE_FORMAT)
+    return display_date_or_time(dt, mango.settings.DISPLAY_DATE_FORMAT)
 
 @register.filter
 def display_time(dt):
-    return display_date_or_time(dt, DISPLAY_TIME_FORMAT)
+    return display_date_or_time(dt, mango.settings.DISPLAY_TIME_FORMAT)
 
 @register.filter
 @stringfilter
 def gravatar(email_hash):
     pairs = []
-    if GRAVATAR_IMAGE_SIZE:
-        pairs.append(('s', GRAVATAR_IMAGE_SIZE))
-    if GRAVATAR_DEFAULT_IMAGE_URL:
-        pairs.append(('d', GRAVATAR_DEFAULT_IMAGE_URL))
+    if mango.settings.GRAVATAR_IMAGE_SIZE:
+        pairs.append(('s', mango.settings.GRAVATAR_IMAGE_SIZE))
+    if mango.settings.GRAVATAR_DEFAULT_IMAGE_URL:
+        pairs.append(('d', mango.settings.GRAVATAR_DEFAULT_IMAGE_URL))
     # Passing a tuple of tuples produces a canonical URL, avoiding unnecessary
     # HTTP requests which could result if a dictionary were passed instead.
     return 'http://www.gravatar.com/avatar/%s?%s' % (email_hash, urllib.urlencode(pairs))
 
 @register.filter
 def is_author_comment(comment):
-    author_urls = AUTHORS.values()
-    if PRIMARY_AUTHOR_URL:
-        author_urls.append(PRIMARY_AUTHOR_URL)
+    email = mango.settings.PRIMARY_AUTHOR_EMAIL
+    author_urls = mango.settings.AUTHORS.values()
+    if mango.settings.PRIMARY_AUTHOR_URL:
+        author_urls.append(mango.settings.PRIMARY_AUTHOR_URL)
     return (author_url(comment) and author_url(comment) in author_urls or
-            PRIMARY_AUTHOR_EMAIL and author_email_hash(comment) == hashlib.md5(PRIMARY_AUTHOR_EMAIL).hexdigest())
+            email and author_email_hash(comment) == hashlib.md5(email).hexdigest())
 
 @register.filter
 def isoformat(timestamp):
 from django.test import TestCase
 from django.test.client import Client
 
-import mango
+import mango.settings
 from mango.main import Document
 from mango.templatetags import mango_extras
 from mango.utils import primary_author_email
 from django.conf.urls.defaults import patterns
 from django.core.urlresolvers import reverse
 
+import mango.settings
 from mango.feeds import atom
 from mango.handlers import flush_cache, moderate, redirect, unsubscribe
-from mango.settings import (CONTACT_FORM, PATH_TO_STATIC, SITEMAP, SOURCE_SUFFIX,
-        SUBSCRIPTIONS, TAGS_PAGE)
 from mango.sitemaps import BlogSitemap
 from mango.views import (archives, contact, index, message_sent, post, search,
         tagged_as, tags, view_source)
 if settings.DEBUG:
     urlpatterns += patterns('',
         (r'^static/(?P<path>.*)$', 'django.views.static.serve',
-                {'document_root': PATH_TO_STATIC}),
+                {'document_root': mango.settings.PATH_TO_STATIC}),
     )
 
-if CONTACT_FORM:
+if mango.settings.CONTACT_FORM:
     urlpatterns += patterns('',
         (r'^contact/$', contact),
         (r'^contact/thanks/$', message_sent),
     )
 
-if SITEMAP:
+if mango.settings.SITEMAP:
     urlpatterns += patterns('',
         (r'^sitemap[.]xml$', 'django.contrib.sitemaps.views.sitemap',
                 {'sitemaps': {'blog': BlogSitemap}}),
     )
 
-if TAGS_PAGE:
+if mango.settings.TAGS_PAGE:
     urlpatterns += patterns('',
         (r'^tags/$', tags),
         (r'^tag/([^/]+)/$', tagged_as),
         (r'^tag/([^/]+)/feed/$', atom),
     )
 
-if SUBSCRIPTIONS:
+if mango.settings.SUBSCRIPTIONS:
     urlpatterns += patterns('',
         (r'^(.+?)/unsubscribe/(\d+)/$', unsubscribe),
     )
     (r'^search$', search),
     (r'^(.+?)/redirect/(.+)?$', redirect),
     (r'^(.+?)/comment/$', post),
-    (r'^(.+?)/%s$' % SOURCE_SUFFIX, view_source),
+    (r'^(.+?)/%s$' % mango.settings.SOURCE_SUFFIX, view_source),
     (r'^(.+?)/$', post),
 )
 from django.utils.safestring import mark_safe
 
 import mango
+import mango.settings
 from mango.decorators import baseurl
 from mango.exceptions import EmptySettingError, InvalidSettingError
-from mango.settings import (AKISMET_API_KEY, BASE_URL, CSS, DOCUMENTS_PATH,
-        JS, MANGO_PATH, PROJECT_PATH, REPLACEMENTS)
 from mango.template import Script, StyleSheet
 
 RE = {
 _console.setLevel(logging.DEBUG)
 _console.setFormatter(_formatter)
 
-_logfile = logging.FileHandler(filename=os.path.join(MANGO_PATH, 'mango.log'), encoding='utf-8')
+_logfile = logging.FileHandler(filename=os.path.join(mango.settings.MANGO_PATH, 'mango.log'), encoding='utf-8')
 _logfile.setLevel(logging.INFO)
 _logfile.setFormatter(_formatter)
 
     while tail:
         fragments.insert(0, tail)
         head, tail = os.path.split(head)
-    return os.path.abspath(os.path.join(PROJECT_PATH, *fragments))
+    return os.path.abspath(os.path.join(mango.settings.PROJECT_PATH, *fragments))
 
 def akismet_api_key():
     def _(): pass
         if _.cache is not None:
             return _.cache[0]
 
-        if AKISMET_API_KEY is None:
+        if mango.settings.AKISMET_API_KEY is None:
             return set(None)
 
         req = Request('http://rest.akismet.com/1.1/verify-key',
-                data=urlencode({'key': AKISMET_API_KEY, 'blog': BASE_URL or baseurl()}),
+                data=urlencode({
+                    'key': mango.settings.AKISMET_API_KEY,
+                    'blog': mango.settings.BASE_URL or baseurl()}),
                 headers={'User-Agent': 'Mango/%s' % mango.VERSION})
 
         with closing(urlopen(req)) as page:
                             'Double-check AKISMET_API_KEY in `mango/settings/custom.py`.')
                 return set(None)
             else:
-                return set(AKISMET_API_KEY)
+                return set(mango.settings.AKISMET_API_KEY)
     return wrapper
 akismet_api_key = akismet_api_key()
 
 def posts_directory():
     """ Creates "posts" directory if it does not already exist. """
     try:
-        os.makedirs(DOCUMENTS_PATH)
+        os.makedirs(mango.settings.DOCUMENTS_PATH)
     except OSError:
-        if not os.path.exists(DOCUMENTS_PATH):
-            raise OSError('Unable to create %s. Check permissions.' % DOCUMENTS_PATH)
+        if not os.path.exists(mango.settings.DOCUMENTS_PATH):
+            raise OSError('Unable to create %s. Check permissions.' % mango.settings.DOCUMENTS_PATH)
 
 def primary_author_email():
     """
             'Add PRIMARY_AUTHOR_EMAIL to `mango/settings/custom.py`.')
 
 def replace(html):
-    if not REPLACEMENTS:
+    if not mango.settings.REPLACEMENTS:
         return html
 
     def replace(text):
     _.cache = None
     def wrapper():
         if _.cache is None:
-            scripts_root = prefix = JS[0]
+            scripts_root = prefix = mango.settings.JS[0]
             if prefix and not urlparse(prefix).scheme and not prefix.startswith('/'):
                 scripts_root = '%s%s' % (reverse('mango.views.index'), prefix)
-            _.cache = [Script('%s%s' % (scripts_root, filename)) for filename in JS[1:]]
+            _.cache = [Script('%s%s' % (scripts_root, f)) for f in mango.settings.JS[1:]]
         return _.cache
     return wrapper
 scripts = scripts()
     _.cache = None
     def wrapper():
         if _.cache is None:
-            stylesheets_root = prefix = CSS[0]
+            stylesheets_root = prefix = mango.settings.CSS[0]
             if prefix and not urlparse(prefix).scheme and not prefix.startswith('/'):
                 stylesheets_root = '%s%s' % (reverse('mango.views.index'), prefix)
             _.cache = [StyleSheet('%s%s' % (stylesheets_root, filename), media)
-                    for media, filenames in CSS[1:]
+                    for media, filenames in mango.settings.CSS[1:]
                     for filename in ((filenames,) if isinstance(
                     filenames, basestring) else filenames)]
         return _.cache
 from django.http import HttpResponseRedirect, HttpResponseServerError
 from django.template.loader import render_to_string
 
-from mango.settings import DISQUS, DISQUS_API_KEY, FORUM, SITE_TITLE, SOURCE_SUFFIX, SUBSCRIPTIONS
+import mango.settings
 from mango.decorators import baseurl
 from mango.exceptions import EmptySettingError
 from mango.forms import CommentForm, ContactForm
 from mango.main import Category, Document, Index
-if SUBSCRIPTIONS:
+if mango.settings.SUBSCRIPTIONS:
     from mango.models import Subscription
 from mango.templatetags.mango_extras import _convert, convert
 from mango.utils import (html_response, logger, primary_author_email, replace,
         message = form.cleaned_data['message']
         subscribe = form.cleaned_data['subscribe']
 
-        if subscribe and SUBSCRIPTIONS: # don't assume that SUBSCRIPTIONS is True
+        # don't assume that `SUBSCRIPTIONS` is True
+        if subscribe and mango.settings.SUBSCRIPTIONS:
             subscriptions = Subscription.objects.filter(
                     subscriber_email=author_email, url=document.permalink())
             if not subscriptions:
 
         try:
             # send request to Disqus
-            comment = DISQUS.create_post(FORUM, thread,
+            comment = mango.settings.DISQUS.create_post(
+                    mango.settings.FORUM, thread,
                     message=message,
                     author_name=author_name,
                     author_email=author_email,
         # send e-mail notification
         post_url = request.build_absolute_uri(reverse(post, args=(path_,)))
         params = {
-            'api_key': hashlib.sha1(DISQUS_API_KEY).hexdigest(),
+            'api_key': hashlib.sha1(mango.settings.DISQUS_API_KEY).hexdigest(),
             'post_id': comment.id,
             'thread_id': thread.id,
             'url': post_url,
             'spam':     ('api_key', 'post_id', 'thread_id'),
         }
         author = u'%s <%s>' % (author_name, author_email)
-        subject = u'[%s] Comment: "%s"' % (SITE_TITLE, document.title_text)
+        subject = u'[%s] Comment: "%s"' % (mango.settings.SITE_TITLE, document.title_text)
         context = {
             'comment': message,
             'commenter': author,
         if path == rel:
             return text_response(found.body)
         else:
-            return HttpResponseRedirect('%s%s' % (found.permalink(), SOURCE_SUFFIX))
+            return HttpResponseRedirect('%s%s' % (found.permalink(),
+                    mango.settings.SOURCE_SUFFIX))
 
     return page_not_found(request)