<repo_name>SP2224/macdown-site-django<file_sep>/base/context_processors.py
from sparkle.models import Channel, Version
from .models import macdown


def latest_version(request):
    try:
        latest_version = macdown.active_versions().latest()
    except Version.DoesNotExist:
        latest_version = None
    return {'latest_version': latest_version}


def channels(request):
    return {'channels': Channel.objects.all()}
<file_sep>/downloads/views.py
from django.http import Http404
from django.views.generic import RedirectView
from sparkle.models import Version
from base.models import macdown


class VersionView(RedirectView):

    permanent = False

    def get_version(self, **kwargs):
        try:
            return macdown.versions.get(**kwargs)
        except Version.DoesNotExist:
            raise Http404

    def get_redirect_url(self, *args, **kwargs):
        return self.get_version(**kwargs).update_url


class LatestVersionView(VersionView):
    def get_version(self, **kwargs):
        return macdown.active_versions().latest()


version = VersionView.as_view()
latest = LatestVersionView.as_view()
<file_sep>/downloads/urls.py
from django.conf.urls import patterns, url
from . import views

urlpatterns = patterns(
    '',
    url(r'^latest/$', views.latest, name='latest'),
    url(r'^v(?P<short_version>\d+(?:\.\w+)+)/$', views.version,
        name='short_version'),
    url(r'^(?P<version>[\.\d]+)/$', views.version, name='version'),
)
<file_sep>/history/urls.py
from django.conf.urls import patterns, url
from . import views

urlpatterns = patterns(
    '',
    url(r'^$', views.all_, name='all'),
    url(r'^(?P<slug>[\w-]+)/$', views.channel, name='channel'),
)
<file_sep>/downloads/tests.py
from django.test import TestCase, Client
from nose.tools import assert_equal, assert_not_equal
from sparkle.models import Version


class DownloadTests(TestCase):
    """Tests for download link generation.
    """
    fixtures = ('macdown', 'macdown_data')

    def test_version_absolute_url(self):
        # Version with readable tag.
        version = Version.objects.get(short_version='0.1.2')
        assert_equal(version.get_absolute_url(), '/download/v0.1.2/')

        # Version without readable tag.
        version = Version.objects.get(version='217')
        assert_equal(version.get_absolute_url(), '/download/217/')

    def test_version(self):
        client = Client()

        # Resolve short version string.
        response = client.get('/download/v0.1.2/')
        assert_equal(response.status_code, 302)
        assert_equal(
            response['Location'],
            'https://github.com/MacDownApp/macdown/releases/download/v0.1.2/'
            'MacDown.app.zip',
        )

        # Resolve version number.
        response = client.get('/download/217/')
        assert_equal(response.status_code, 302)
        assert_equal(response['Location'], 'http://d.pr/f/3qn7+')

    def test_latest_version(self):
        client = Client()

        # Should point to the real lastest active version.
        response = client.get('/download/latest/')
        location = response['Location']
        assert_equal(response.status_code, 302)

        # Should not point to a newer, but non-active version.
        response = client.get('/download/v0.1.2/')
        assert_equal(location, response['Location'])
        response = client.get('/download/217/')
        assert_not_equal(location, response['Location'])
<file_sep>/sparkle/migrations/0002_auto_20140701_1935.py
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations


class Migration(migrations.Migration):

    dependencies = [
        ('sparkle', '0001_initial'),
    ]

    operations = [
        migrations.CreateModel(
            name='Channel',
            fields=[
                ('id', models.AutoField(serialize=False, primary_key=True, auto_created=True, verbose_name='ID')),
                ('name', models.CharField(verbose_name='name', max_length=50)),
                ('slug', models.SlugField(verbose_name='slug', unique=True)),
            ],
            options={
                'verbose_name': 'channel',
                'verbose_name_plural': 'channels',
            },
            bases=(models.Model,),
        ),
        migrations.AlterModelOptions(
            name='version',
            options={'ordering': ('-publish_at',), 'verbose_name': 'version', 'verbose_name_plural': 'versions', 'get_latest_by': 'version'},
        ),
        migrations.AddField(
            model_name='application',
            name='default_channel',
            field=models.ForeignKey(null=True, verbose_name='default channel', to='sparkle.Channel'),
            preserve_default=True,
        ),
        migrations.AddField(
            model_name='version',
            name='channels',
            field=models.ManyToManyField(verbose_name='channels', to='sparkle.Channel'),
            preserve_default=True,
        ),
    ]
<file_sep>/history/models.py
from django.core.urlresolvers import reverse
from sparkle.models import Channel


def channel_get_absolute_url(obj):
    return reverse('history:channel', kwargs={'slug': obj.slug})

Channel.get_absolute_url = channel_get_absolute_url
<file_sep>/sparkle/forms/__init__.py
from django import forms
from .widgets import PopupGhostdownInput


class VersionAdminForm(forms.ModelForm):
    class Meta:
        fields = (
            'application', 'channels', 'title', 'version', 'short_version',
            'dsa_signature', 'length', 'release_notes',
            'minimum_system_version', 'update_url', 'publish_at',
        )
<file_sep>/base/tests.py
from django.test import TestCase
from nose.tools import assert_equal
from sparkle.models import Application
from .models import macdown


class BaseTests(TestCase):
    """Tests for base module.
    """
    fixtures = ('macdown', 'macdown_data')

    def test_macdown(self):
        assert_equal(macdown, Application.objects.get(slug='macdown'))
<file_sep>/sparkle/views.py
from django.utils.translation import ugettext as _
from django.http import Http404
from django.views.generic.detail import DetailView
from .models import (
    Application, Channel, SystemProfileReport, SystemProfileReportRecord,
)


class ChannelView(DetailView):

    model = Channel
    context_object_name = 'channel'
    slug_url_kwarg = 'channel_slug'
    content_type = 'application/xml'
    template_name = 'sparkle/appcast.xml'

    def get_object(self, queryset=None):
        try:
            self.application = Application.objects.get(
                slug=self.kwargs['app_slug'],
            )
        except Application.DoesNotExist:
            raise Http404(
                _("No {verbose_name} found matching the query").format(
                    verbose_name=Application._meta.verbose_name,
                )
            )
        if self.slug_url_kwarg not in self.kwargs:
            obj = self.application.default_channel
        else:
            obj = super(ChannelView, self).get_object(queryset)
        return obj

    def get_context_data(self, **kwargs):
        data = super(ChannelView, self).get_context_data(**kwargs)
        data.update({
            'application': self.application,
            'active_versions': self.application.active_versions(self.object)
        })
        return data

    def render_to_response(self, context, **response_kwargs):
        """Record system profile reports before we send out the response.
        """
        if self.request.GET:
            # Create a report and records of the keys/values
            report = SystemProfileReport.objects.create(
                ip_address=self.request.META.get('REMOTE_ADDR'),
            )
            for key in self.request.GET:
                SystemProfileReportRecord.objects.create(
                    report=report, key=key, value=self.request.GET[key],
                )
        return super(ChannelView, self).render_to_response(
            context, **response_kwargs
        )


channel = ChannelView.as_view()
<file_sep>/blog/posts.py
import os
import re
import yaml
from django.utils.functional import cached_property
from django.conf import settings
from django.core.urlresolvers import reverse
from django.apps import apps
from django.template import TemplateDoesNotExist
from base.markdown import render


FRONT_MATTER_PATTERN = re.compile(r'^---\n(.*?\n)---', re.DOTALL)


class PostDoesNotExist(TemplateDoesNotExist):
    pass


class Post:

    FILENAME_PATTERN = re.compile(r'^(\d+)-([\w-]+)$')

    def __init__(self, filename, dirpath=None):
        filename, ext = os.path.splitext(filename)
        match = self.FILENAME_PATTERN.match(filename)
        if match is None:
            raise PostDoesNotExist(
                os.path.join(dirpath, ''.join([filename, ext]))
            )
        self.id = int(match.group(1))
        self.slug = match.group(2)
        self.renderer = None
        if dirpath is None:
            dirpath = default_post_dir
        self.dirpath = dirpath
        self.filename = ''.join([filename, ext])

    def __getattr__(self, key):
        try:
            value = self.meta[key]
        except KeyError:
            raise AttributeError(key)
        return value

    @property
    def abspath(self):
        return os.path.join(self.dirpath, self.filename)

    @cached_property
    def file_content(self):
        """Returns a 2-tuple (meta, content).
        """
        full_content = self.read()
        front_matter, offset = get_front_matter(full_content)
        return (front_matter, full_content[offset:])

    @cached_property
    def meta(self):
        return self.file_content[0]

    @cached_property
    def rendered_content(self):
        self.renderer, rendered = render(self.file_content[1])
        return rendered

    def get_absolute_url(self):
        return reverse('blog:post', kwargs={'id': self.id, 'slug': self.slug})

    def read(self):
        return load_post_source(self.filename, self.dirpath)


def calculate_post_dir():
    app_config = apps.get_app_config('blog')
    return os.path.join(app_config.path, 'posts')


default_post_dir = calculate_post_dir()


def get_post_filelist(post_dir=None):
    if post_dir is None:
        post_dir = default_post_dir
    filelist = os.listdir(post_dir)
    filelist.sort()
    return filelist


# id => post instance
_post_cache = {}


def get_post_list(post_dir=None):
    posts = []
    for filename in reversed(get_post_filelist(post_dir)):
        try:
            base, _ = os.path.splitext(filename)
            post_id = int(Post.FILENAME_PATTERN.match(base).group(1))
            post = _post_cache[post_id]
        except (AttributeError, KeyError):
            try:
                post = Post(filename)
            except PostDoesNotExist:
                continue
            _post_cache[post.id] = post
        if post.title:
            posts.append(post)
    return posts


def get_post(post_id, post_dir=None):
    try:
        post = _post_cache[post_id]
    except KeyError:
        post = Post(get_post_filename(id=post_id, post_dir=post_dir))
        _post_cache[post_id] = post
    return post


def get_post_filename(id, post_dir=None):
    prefix_pattern = re.compile(r'^0*{id}-'.format(id=id))
    for filename in get_post_filelist(post_dir):
        if prefix_pattern.match(filename):
            return filename
    if post_dir is None:
        post_dir = default_post_dir
    raise PostDoesNotExist(
        'ID {id} in directory {dir}'.format(id=id, dir=post_dir)
    )


def get_post_abspath(filename, post_dir=None):
    if post_dir is None:
        post_dir = default_post_dir
    return os.path.join(post_dir, filename)


def load_post_source(filename, post_dir=None):
    filepath = get_post_abspath(filename, post_dir)
    try:
        with open(filepath, 'rb') as f:
            return f.read().decode(settings.FILE_CHARSET)
    except IOError:
        pass
    raise PostDoesNotExist(filepath)


def get_front_matter(markdown):
    """Returns a 2-tuple (front_matter, content_offset)
    """
    front_matter = None
    offset = 0
    match = FRONT_MATTER_PATTERN.search(markdown)
    if match:
        try:
            front_matter = yaml.load(match.group(1))
        except yaml.YAMLError:
            pass
        else:
            offset = match.end(0) + 1   # Eat newline after closing "---"
    return (front_matter, offset)
<file_sep>/blog/views.py
from django.http import Http404, HttpResponsePermanentRedirect
from django.views.generic import TemplateView
from .posts import PostDoesNotExist, get_post_list, get_post
from .utils import resolve_prism_languages


class PostListView(TemplateView):

    template_name = 'blog/post_list.html'

    def get_context_data(self, **kwargs):
        posts = get_post_list()
        data = super().get_context_data()
        data.update({'posts': posts})
        return data


class PostDetailView(TemplateView):

    template_name = 'blog/post_detail.html'

    def get(self, request, *args, **kwargs):
        post_id = int(kwargs['id'])
        post_slug = kwargs.get('slug')
        try:
            post = get_post(post_id)
        except PostDoesNotExist:
            raise Http404
        if post.slug != post_slug or kwargs['id'] != str(post_id):
            canonical_url = post.get_absolute_url()
            return HttpResponsePermanentRedirect(redirect_to=canonical_url)
        self.post = post
        return super().get(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        try:
            page_meta = self.post.meta
            content = self.post.rendered_content
            renderer = self.post.renderer
            assert page_meta is not None
            assert renderer is not None
        except (AssertionError, PostDoesNotExist):
            raise Http404
        data = super().get_context_data()
        data.update({
            'post': self.post,
            'page': page_meta,
            'content': content,
            'languages': resolve_prism_languages(renderer.languages),
        })
        return data


post_list = PostListView.as_view()
post_detail = PostDetailView.as_view()
<file_sep>/__/wsgi.py
"""
WSGI config for macdown project.

It exposes the WSGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/dev/howto/deployment/wsgi/
"""

import os

# This needs to be set BEFORE Cling is imported.
# https://github.com/kennethreitz/dj-static/issues/28
os.environ.setdefault('DJANGO_SETTINGS_MODULE', '__.settings.deploy')

from django.core.wsgi import get_wsgi_application
from dj_static import Cling
application = Cling(get_wsgi_application())
<file_sep>/__/settings/local_uranusjr.py
from .base import *     # noqa

SECRET_KEY = '!)<KEY>'

DEBUG = True

TEMPLATE_DEBUG = True

DATABASES['default'] = {
    'ENGINE': 'django.db.backends.sqlite3',
    'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
<file_sep>/base/templatetags/base_tags.py
from __future__ import division
from django.utils.translation import ugettext as _
from django.template import Library
from django.template.defaultfilters import stringfilter

register = Library()


@register.simple_tag(takes_context=True)
def absolute_uri(context, path):
    return context['request'].build_absolute_uri(path)


@register.filter
@stringfilter
def volumize(value):
    try:
        value = float(value)
    except ValueError:
        value = 0
    if value == 0:
        return _('0 bytes')
    elif value == 1:
        return _('1 byte')
    for unit in (_('bytes'), _('KB'), _('MB'), _('GB'),):
        if -1024 < value < 1024:
            return _('{value:3.1f} {unit}').format(value=value, unit=unit)
        value /= 1024
    return '{value:3.1f} {unit}'.format(value=value, unit=_('TB'))
<file_sep>/sparkle/migrations/0003_auto_20150411_1654.py
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations


class Migration(migrations.Migration):

    dependencies = [
        ('sparkle', '0002_auto_20140701_1935'),
    ]

    operations = [
        migrations.AlterField(
            model_name='systemprofilereport',
            name='ip_address',
            field=models.GenericIPAddressField(verbose_name='IP address'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='version',
            name='application',
            field=models.ForeignKey(related_name='versions', to='sparkle.Application', verbose_name='application'),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='version',
            name='channels',
            field=models.ManyToManyField(related_name='versions', verbose_name='channels', to='sparkle.Channel'),
            preserve_default=True,
        ),
    ]
<file_sep>/blog/feeds.py
from django.core.urlresolvers import reverse
from django.utils import feedgenerator
from django.utils.translation import ugettext_lazy as _
from django.contrib.syndication.views import Feed
from .posts import get_post_list


MACDOWN_DESCRIPTION = _(
    '<p>MacDown is an open source Markdown editor for OS X, released under '
    'the MIT License. It is heavily influenced by '
    '<a href="https://twitter.com/chenluois"><NAME></a>’s '
    '<a href="http://mouapp.com">Mou</a>.</p>'
)


class PostsFeed(Feed):
    """Common parent class for RSS and Atom feeds
    """

    title = _('The MacDown Blog')
    description = MACDOWN_DESCRIPTION

    def link(self):
        return reverse('blog:list')

    def items(self):
        return get_post_list()

    def item_title(self, item):
        return item.title

    def item_description(self, item):
        return item.rendered_content

    def item_link(self, item):
        return item.get_absolute_url()


class PostsRss201rev2Reed(PostsFeed):
    feed_type = feedgenerator.Rss201rev2Feed


class PostsAtom1Feed(PostsFeed):
    feed_type = feedgenerator.Atom1Feed


rss201rev2 = PostsRss201rev2Reed()
atom1 = PostsAtom1Feed()
<file_sep>/pages/urls.py
from django.conf.urls import patterns, url
from . import views

urlpatterns = patterns(
    '',
    url(r'^$', views.home, name='home'),
    url(r'^features/$', views.features, name='features'),
    url(r'^(?P<name>[\w-]+)/$', views.page, name='page'),
)
<file_sep>/history/views.py
from django.http import Http404
from django.core.urlresolvers import reverse_lazy
from django.views.generic import ListView
from sparkle.models import Channel
from base.models import macdown


class AllHistoryView(ListView):
    def get_queryset(self):
        return macdown.active_versions()


class ChannelHistoryView(ListView):

    def get_queryset(self):
        try:
            self.channel = Channel.objects.get(slug=self.kwargs.get('slug'))
        except Channel.DoesNotExist:
            raise Http404
        return macdown.active_versions(channel=self.channel)

    def get_context_data(self):
        data = super().get_context_data()
        data.update({'channel': self.channel})
        return data


all_ = AllHistoryView.as_view()
channel = ChannelHistoryView.as_view()
<file_sep>/sparkle/urls.py
from django.conf.urls import patterns, url
from .views import channel

urlpatterns = patterns(
    '',
    url(r'^(?P<app_slug>[\w-]+)/appcast\.xml$', channel,
        name='sparkle_application_default_channel'),
    url(r'^(?P<app_slug>[\w-]+)/(?P<channel_slug>[\w-]+)/appcast\.xml$',
        channel, name='sparkle_application_channel')
)
<file_sep>/blog/tests.py
import os
import tempfile
from django.test import TestCase
from nose.tools import assert_equal, assert_raises
from . import posts


EXAMPLE_POST_CONTENT = (
    """---
title: Test Post
author: <NAME>
---

Lorem ipsum.
""")


class PostDirTests(TestCase):
    """Tests for Post lookup-related things.
    """
    def setUp(self):
        self.post_dir = os.path.join(os.path.dirname(__file__), 'posts')

    def test_post_dir(self):
        assert_equal(posts.default_post_dir, self.post_dir)

    def test_get_post_abspath(self):
        post_path = os.path.join(self.post_dir, 'foo')
        assert_equal(posts.get_post_abspath('foo'), post_path)

    def test_does_not_exist(self):
        with assert_raises(posts.PostDoesNotExist):
            posts.Post('loremipsum', self.post_dir)

    def test_default_dir(self):
        post = posts.Post('01-the-macdown-blog.md')
        assert_equal(post.dirpath, self.post_dir)


class PostTests(TestCase):
    """Tests for Post model.
    """
    def setUp(self):
        fd, path = tempfile.mkstemp(prefix='1-', suffix='.md')
        f = os.fdopen(fd, 'w')
        f.write(EXAMPLE_POST_CONTENT)
        f.close()
        dirpath, filename = os.path.split(path)
        self.post = posts.Post(filename, dirpath)
        self.filename = filename

    def tearDown(self):
        os.remove(self.post.abspath)

    def test_load(self):
        pass    # If this fails, Post initialization failed.

    def test_filename(self):
        assert_equal(self.post.filename, self.filename)

    def test_file_content(self):
        fm, content = self.post.file_content
        assert_equal(fm, {'title': 'Test Post', 'author': '<NAME>'})
        assert_equal(content.strip(), 'Lorem ipsum.')

    def test_meta(self):
        assert_equal(self.post.meta, {
            'title': 'Test Post', 'author': '<NAME>',
        })
        assert_equal(self.post.title, 'Test Post')
        assert_equal(self.post.author, '<NAME>')
        with assert_raises(AttributeError):
            self.post.foobar

    def test_rendered_content(self):
        assert_equal(self.post.rendered_content, '<p>Lorem ipsum.</p>\n')

    def test_get_absolute_url(self):
        # Strip "1-" and ".md" from filename to get the slug.
        expected = '/blog/post/1/{slug}/'.format(slug=self.filename[2:-3])
        assert_equal(self.post.get_absolute_url(), expected)
<file_sep>/pages/views.py
from django.http import Http404
from django.template.base import TemplateDoesNotExist
from django.template.loader import get_template
from django.views.generic import TemplateView

from .utils import get_language_infos


class HomeView(TemplateView):
    template_name = 'pages/home.html'


class PageView(TemplateView):

    def get(self, request, *args, **kwargs):
        self.name = kwargs['name']
        return super().get(request, *args, **kwargs)

    def get_template_names(self):
        template_name = 'pages/{name}.html'.format(name=self.name)
        try:
            get_template(template_name)
        except TemplateDoesNotExist:
            raise Http404
        return [template_name]


class FeaturesView(TemplateView):

    template_name = 'pages/features.html'

    def get_context_data(self, **kwargs):
        data = super().get_context_data(**kwargs)
        data['language_infos'] = get_language_infos()
        return data


home = HomeView.as_view()
page = PageView.as_view()
features = FeaturesView.as_view()
<file_sep>/blog/utils.py
from base.markdown import PRISM_LANGAUGE_DEPENDENCIES


def resolve_prism_languages(language_set):
    """Resolve language aliases, add required dependencies, and order them.

    Returns a list of languages used. The more dependant langauge will be
    listed LAST.
    """
    languages = []

    def put_lang(lang):
        try:
            languages.remove(lang)
        except ValueError:  # Not found.
            pass
        languages.append(lang)

    for lang in language_set:
        put_lang(lang)
        while lang in PRISM_LANGAUGE_DEPENDENCIES:
            lang = PRISM_LANGAUGE_DEPENDENCIES[lang]
            put_lang(lang)

    return languages
<file_sep>/pages/utils.py
import base64
import json
import os
import re

from django.apps import apps
from django.utils.six.moves import urllib


GITHUB_API_BASE_URL = 'https://api.github.com/'
STABLE_TAG_PATTERN = re.compile(r'^v[\d\.]+$')


def get_endpoint(path, params=None):
    url = urllib.parse.urljoin(GITHUB_API_BASE_URL, path)
    if params is not None:
        url = url + '?' + '&'.join('{k}={v}'.format(
            k=key, v=params[key],
        ) for key in params)
    response = urllib.request.urlopen(url)
    return json.loads(response.read().decode('utf8'))


def get_latest_tag():
    tag_data_list = get_endpoint('/repos/MacDownApp/macdown/tags')
    tag = None
    for tag_data in tag_data_list:
        tag_name = tag_data['name']
        if STABLE_TAG_PATTERN.match(tag_name):
            tag = tag_name
            break
    assert tag is not None
    return tag


def download_endpoint(endpoint, ref, encoding='utf-8'):
    data = get_endpoint(endpoint, params={'ref': ref})
    content_str = base64.b64decode(data['content']).decode(encoding)
    return content_str


def get_prism_languages():
    """Use the GitHub API to get a list of currently contained Prism languages.
    """
    # Get Git URL of Prism submodule at the tag.
    data = get_endpoint(
        '/repos/MacDownApp/macdown/contents/Dependency/prism',
        params={'ref': get_latest_tag()},
    )
    components_str = download_endpoint(
        endpoint='/repos/PrismJS/prism/contents/components.js',
        ref=data['sha'],
    )
    # Make this string JSON-compatible.
    components_str = components_str[
        components_str.find('{'):components_str.rfind('}') + 1
    ]
    components_str_lines = [
        line for line in components_str.splitlines(True)
        if not line.strip().startswith('//')
    ]
    components = json.loads(''.join(components_str_lines))

    languages = components['languages']
    return languages


def get_language_aliases():
    """Get a list of MacDown-maintained language aliases.
    """
    info_str = download_endpoint(
        endpoint=(
            '/repos/MacDownApp/macdown/contents/MacDown/Resources/'
            'syntax_highlighting.json'
        ),
        ref=get_latest_tag(),
    )
    info = json.loads(info_str)
    return info['aliases']


def get_language_notes():
    """Get custom notes for languages.

    The values are raw HTML content. A key can be either a Prism language ID, or
    a MacDown language alias.
    """
    app_config = apps.get_app_config('pages')
    path = os.path.join(
        app_config.path, 'static', 'pages', 'data', 'language_notes.json',
    )
    with open(path) as f:
        return json.load(f)


LANGUAGE_INFO_CACHE = None


def get_language_infos():
    if LANGUAGE_INFO_CACHE is None:
        languages = get_prism_languages()
        del languages['meta']
        infos = {lang: '' for lang in languages if not lang.endswith('-extras')}

        aliases = get_language_aliases()
        infos.update({
            k: 'Alias to <code>{lang}</code>.'.format(lang=aliases[k])
            for k in aliases
        })

        notes = get_language_notes()
        for lang in notes:
            infos[lang] = notes[lang]

        infos = [(key, infos[key]) for key in sorted(infos.keys())]
        global LANGUAGE_INFO_CACHE
        LANGUAGE_INFO_CACHE = infos
    return LANGUAGE_INFO_CACHE
<file_sep>/sparkle/models/compat.py
try:
    from django.db.models import GenericIPAddressField
except ImportError:
    # Django 1.6 or earlier. Remove this when dropping support to Django 1.7.
    from django.db.models import IPAddressField as GenericIPAddressField  # noqa
<file_sep>/base/middleware.py
import re
from django.http import HttpResponsePermanentRedirect
from django.conf import settings


class SecureRequiredMiddleware(object):
    """Forces HTTPS access for paths specified.
    """
    def __init__(self):
        try:
            pattern = settings.SECURE_REQUIRED_PATH_PATTERN
        except AttributeError:
            self.path_regex = None
        else:
            self.path_regex = re.compile(pattern)

    def process_request(self, request):
        if self.path_regex is None:
            return
        full_path = request.get_full_path()
        if not request.is_secure() and self.path_regex.match(full_path):
            request_url = request.build_absolute_uri()
            secure_url = request_url.replace('http://', 'https://')
            return HttpResponsePermanentRedirect(secure_url)
        return None
<file_sep>/pages/tests.py
import lxml.html
from lxml.cssselect import CSSSelector
from nose.tools import assert_equal, assert_not_equal

from django.test import TestCase

from sparkle.models import Version

from base.models import macdown


class PageTests(TestCase):
    """Tests for page loading.
    """
    fixtures = ('macdown', 'macdown_data')

    def _check_download_buttons(self, tree):
        """Check that download links in the tree are correct.

        There should be at least one download link, and all links should point
        to the version specified.
        """
        matches = CSSSelector('.download.button')(tree)
        assert_not_equal(len(matches), 0)
        for match in matches:
            assert_equal(match.get('href'), '/download/latest/')

    def test_home(self):
        # Should load.
        response = self.client.get('/')
        assert_equal(response.status_code, 200)
        tree = lxml.html.fromstring(response.content)

        # Should contain download link in top navbar.
        for match in CSSSelector('.top-bar a')(tree):
            if match.get('href') == '/download/latest/':
                break
        else:   # This happens if no matches are found
            self.fail('Download link not found in top navbar.')

    def test_features(self):
        response = self.client.get('/features/')
        assert_equal(response.status_code, 200)

        tree = lxml.html.fromstring(response.content)
        self._check_download_buttons(tree)

    def test_faq(self):
        response = self.client.get('/faq/')
        assert_equal(response.status_code, 200)

        tree = lxml.html.fromstring(response.content)
        self._check_download_buttons(tree)


class NoDownloadLinkTests(TestCase):
    """Test the download link if versions does not exist.
    """
    fixtures = ('macdown', 'macdown_data')

    def _test_home(self):
        # Should load.
        response = self.client.get('/')
        assert_equal(response.status_code, 200)
        tree = lxml.html.fromstring(response.content)

        # Should not contain download link in navbar.
        assert_equal(len(CSSSelector('.top-bar li.active a')(tree)), 0)

        # Should not contain download link.
        assert_equal(len(CSSSelector('.download.button')(tree)), 0)

    def test_no_default(self):
        # Remove versions from default channel.
        macdown.active_versions().delete()
        self._test_home()

    def test_nothing_at_all(self):
        # Remove all versions.
        Version.objects.all().delete()
        self._test_home()
<file_sep>/sparkle/forms/widgets.py
#!/usr/bin/env python
# -*- coding: utf-8

from __future__ import unicode_literals
from django.template.loader import get_template
from ghostdown.forms.widgets import GhostdownInput


class PopupGhostdownInput(GhostdownInput):
    def get_template(self):
        return get_template('sparkle/includes/ghostdown_editor.html')
<file_sep>/README.rst
#LOG = This is an amazing project
===================
macdown-site
===================

This is the source code of the official site for MacDown_. Please click here_
if you’re looking for the real MacDown repository.

.. _Macdown: http://macdown.uranusjr.com
.. _here: https://github.com/MacDownApp/macdown
<file_sep>/base/utils.py
from sparkle.models import Version


class MacDown(object):
    objects = Version.objects.filter(application__slug='macdown')
<file_sep>/sparkle/models/query.py
from django.utils.timezone import now
from django.db.models.query import QuerySet


class VersionQuerySet(QuerySet):
    def active(self, channel=None):
        qs = self.filter(publish_at__lte=now())
        if channel is None:
            return qs
        return qs.filter(channels__in=[channel])
<file_sep>/sparkle/migrations/0001_initial.py
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations
import ghostdown.models.fields
import django.utils.timezone


class Migration(migrations.Migration):

    dependencies = [
    ]

    operations = [
        migrations.CreateModel(
            name='Application',
            fields=[
                ('id', models.AutoField(primary_key=True, verbose_name='ID', auto_created=True, serialize=False)),
                ('name', models.CharField(verbose_name='name', max_length=50)),
                ('slug', models.SlugField(verbose_name='slug', unique=True)),
            ],
            options={
                'verbose_name_plural': 'applications',
                'verbose_name': 'application',
            },
            bases=(models.Model,),
        ),
        migrations.CreateModel(
            name='SystemProfileReport',
            fields=[
                ('id', models.AutoField(primary_key=True, verbose_name='ID', auto_created=True, serialize=False)),
                ('ip_address', models.IPAddressField(verbose_name='IP address')),
                ('created_at', models.DateTimeField(verbose_name='created at', auto_now_add=True)),
            ],
            options={
            },
            bases=(models.Model,),
        ),
        migrations.CreateModel(
            name='SystemProfileReportRecord',
            fields=[
                ('id', models.AutoField(primary_key=True, verbose_name='ID', auto_created=True, serialize=False)),
                ('key', models.CharField(verbose_name='key', max_length=100)),
                ('value', models.CharField(verbose_name='value', max_length=80)),
                ('report', models.ForeignKey(to='sparkle.SystemProfileReport', verbose_name='report')),
            ],
            options={
            },
            bases=(models.Model,),
        ),
        migrations.CreateModel(
            name='Version',
            fields=[
                ('id', models.AutoField(primary_key=True, verbose_name='ID', auto_created=True, serialize=False)),
                ('title', models.CharField(verbose_name='title', max_length=100)),
                ('version', models.CharField(verbose_name='version', help_text='If you use short_version, this can be the internal version number or build number that will not be shown. In any case, this string is compared to CFBundleVersion of your bundle.', max_length=10)),
                ('short_version', models.CharField(verbose_name='short version', max_length=50, help_text='A user-displayable version string.', blank=True)),
                ('dsa_signature', models.CharField(verbose_name='DSA signature', max_length=80)),
                ('length', models.CharField(verbose_name='length', max_length=20)),
                ('release_notes', ghostdown.models.fields.GhostdownField(verbose_name='release notes', blank=True)),
                ('minimum_system_version', models.CharField(verbose_name='minimum system version', max_length=10)),
                ('update_url', models.URLField(verbose_name='update URL')),
                ('created_at', models.DateTimeField(verbose_name='created at', auto_now_add=True)),
                ('publish_at', models.DateTimeField(default=django.utils.timezone.now, verbose_name='published at', help_text='When this upate will be (automatically) published.')),
                ('application', models.ForeignKey(to='sparkle.Application', verbose_name='application')),
            ],
            options={
                'verbose_name_plural': 'versions',
                'verbose_name': 'version',
                'get_latest_by': 'publish_at',
                'ordering': ('-publish_at',),
            },
            bases=(models.Model,),
        ),
    ]
<file_sep>/sparkle/conf.py
from django.conf import settings

SYSTEM_PROFILES_VISIBLE = getattr(
    settings, 'SPARKLE_SYSTEM_PROFILES_VISIBLE', False
)
<file_sep>/requirements.txt
cython
django>=1.7,<1.8
dj-database-url
dj-static>=0.0.6
django-absolute
django-appconf
django-ghostdown
django-grappelli
mistune
psycopg2
pystache
PyYAML
six
waitress
<file_sep>/blog/urls.py
from django.conf.urls import patterns, url
from django.core.urlresolvers import reverse_lazy
from django.views.generic import RedirectView
from . import feeds, views

urlpatterns = patterns(
    '',
    url(r'^$', views.post_list, name='list'),
    url(r'^post/(?P<id>\d+)/$', views.post_detail),
    url(r'^post/(?P<id>\d+)/(?P<slug>.+?)/$', views.post_detail, name='post'),

    url(r'^feed/atom\.xml$', feeds.atom1, name='atom1'),

    # Deprecated.
    url(r'^feed/rss201rev2/$', feeds.rss201rev2, name='rss201rev2'),
    url(r'^feed/atom1/$', RedirectView.as_view(
        url=reverse_lazy('blog:atom1'), permanent=True,
    )),
)
<file_sep>/__/urls.py
from django.conf.urls import patterns, include, url
from django.contrib import admin

urlpatterns = patterns(
    '',
    url(r'^sparkle/', include('sparkle.urls')),
    url(r'^download/', include('downloads.urls', namespace='downloads')),
    url(r'^blog/', include('blog.urls', namespace='blog')),
    url(r'^history/', include('history.urls', namespace='history')),
    url(r'^grappelli/', include('grappelli.urls')),
    url(r'^admin/', include(admin.site.urls)),
    url(r'^', include('pages.urls', namespace='pages')),
)
<file_sep>/downloads/models.py
from django.core.urlresolvers import reverse
from sparkle.models import Version


def version_get_absolute_url(obj):
    if obj.short_version:
        return reverse('downloads:short_version', kwargs={
            'short_version': obj.short_version
        })
    else:
        return reverse('downloads:version', kwargs={'version': obj.version})

Version.get_absolute_url = version_get_absolute_url
<file_sep>/base/models.py
from django.utils.functional import SimpleLazyObject
from sparkle.models import Application


def get_macdown():
    return Application.objects.get_or_create(slug='macdown')[0]

macdown = SimpleLazyObject(get_macdown)
<file_sep>/sparkle/models/managers.py
from django.db import models
from .query import VersionQuerySet


class VersionManager(models.Manager):

    use_for_related_fields = True

    def get_queryset(self):
        return VersionQuerySet(self.model, using=self._db)

    def active(self, channel=None):
        return self.get_queryset().active(channel=channel)
<file_sep>/base/markdown.py
import mistune


PRISM_LANGUAGE_ALIASES = {
    'c++': 'cpp',
    'coffee': 'coffeescript',
    'coffee-script': 'coffeescript',
    'cs': 'csharp',
    'html': 'markup',
    'js': 'javascript',
    'json': 'javascript',
    'objective-c': 'objectivec',
    'obj-c': 'objectivec',
    'objc': 'objectivec',
    'py': 'python',
    'rb': 'ruby',
    'sh': 'bash',
    'xml': 'markup',
}


PRISM_LANGAUGE_DEPENDENCIES = {
    'aspnet': 'markup',
    'bash': 'clike',
    'c': 'clike',
    'coffeescript': 'javascript',
    'cpp': 'c',
    'csharp': 'clike',
    'go': 'clike',
    'groovy': 'clike',
    'java': 'clike',
    'javascript': 'clike',
    'objectivec': 'c',
    'php': 'clike',
    'ruby': 'clike',
    'scala': 'java',
    'scss': 'css',
    'swift': 'clike',
}


class Renderer(mistune.Renderer):

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.languages = set()

    def block_code(self, code, lang=None):
        if lang in PRISM_LANGUAGE_ALIASES:
            lang = PRISM_LANGUAGE_ALIASES[lang]
        if lang is not None:
            self.languages.add(lang)
        return super().block_code(code, lang)


def render(markdown):
    """Render given Markdown input.

    Returns a 2-tuple (renderer, HTML).
    """
    renderer = Renderer()
    rendered = mistune.markdown(markdown, renderer=renderer)
    return (renderer, rendered,)


def render_to_html(markdown):
    """Render given Markdown input to HTML.

    Returns rendered HTML as string.
    """
    return render(markdown)[1]
