Example #1
0
def generate_rsd(app):
    """Generate the RSD definition for this application apis."""
    from zine.application import url_for
    document = __import__('xml.dom.minidom', None, None, ['']).Document()
    root = document.appendChild(document.createElement('rsd'))
    root.setAttribute('version', '1.0')
    root.setAttribute('xmlns', 'http://archipelago.phrasewise.com/rsd')
    service = root.appendChild(document.createElement('service'))

    attributes = [('engineName', 'Zine'),
                  ('engineLink', 'http://zine.pocoo.org/'),
                  ('homePageLink', url_for('blog/index', _external=True))]

    for attr, value in attributes:
        service.appendChild(document.createElement(attr)) \
               .appendChild(document.createTextNode(value))

    apis = service.appendChild(document.createElement('apis'))
    for name, (blog_id, preferred, endpoint) in app.apis.iteritems():
        element = apis.appendChild(document.createElement('api'))
        element.setAttribute('name', name)
        element.setAttribute('blogID', str(blog_id))
        element.setAttribute('preferred', preferred and 'true' or 'false')
        element.setAttribute('apiLink', url_for(endpoint, _external=True))

    return document.toxml('utf-8')
Example #2
0
def generate_rsd(app):
    """Generate the RSD definition for this application apis."""
    from zine.application import url_for
    document = __import__('xml.dom.minidom', None, None, ['']).Document()
    root = document.appendChild(document.createElement('rsd'))
    root.setAttribute('version', '1.0')
    root.setAttribute('xmlns', 'http://archipelago.phrasewise.com/rsd')
    service = root.appendChild(document.createElement('service'))

    attributes = [('engineName', 'Zine'),
                  ('engineLink', 'http://zine.pocoo.org/'),
                  ('homePageLink', url_for('blog/index', _external=True))]

    for attr, value in attributes:
        service.appendChild(document.createElement(attr)) \
               .appendChild(document.createTextNode(value))

    apis = service.appendChild(document.createElement('apis'))
    for name, (blog_id, preferred, endpoint) in app.apis.iteritems():
        element = apis.appendChild(document.createElement('api'))
        element.setAttribute('name', name)
        element.setAttribute('blogID', str(blog_id))
        element.setAttribute('preferred', preferred and 'true' or 'false')
        element.setAttribute('apiLink', url_for(endpoint, _external=True))

    return document.toxml('utf-8')
Example #3
0
def show_category(req, slug, page=1):
    """Show all posts categoryged with a given category slug.

    Available template variables:

        `posts`:
            a list of post objects we want to display

        `pagination`:
            a pagination object to render a pagination

        `category`
            the category object for this page.

    :Template name: ``show_category.html``
    :URL endpoint: ``blog/show_category``
    """
    category = Category.query.filter_by(slug=slug).first(True)
    per_page = req.app.theme.settings['category.per_page']
    data = category.posts.theme_lightweight('category') \
                   .published().get_list(page=page, per_page=per_page,
                                         endpoint='blog/show_category',
                                         url_args=dict(slug=slug))

    add_link('alternate', url_for('blog/atom_feed', category=slug),
             'application/atom+xml', _(u'All posts in category %s') % category.name)
    return render_response('show_category.html', category=category, **data)
Example #4
0
def show_author(req, username, page=1):
    """Show the user profile of an author / editor or administrator.

    Available template variables:

        `posts`:
            a list of post objects this author wrote and are
            visible on this page.

        `pagination`:
            a pagination object to render a pagination

        `user`
            The user object for this author

    :Template name: ``show_author.html``
    :URL endpoint: ``blog/show_author``
    """
    user = User.query.filter_by(username=username).first()
    if user is None or not user.is_author:
        raise NotFound()

    per_page = req.app.theme.settings['author.per_page']
    data = user.posts.theme_lightweight('author').published() \
                     .get_list(page=page, per_page=per_page,
                               endpoint='blog/show_author',
                               url_args=dict(username=user.username))

    add_link('alternate', url_for('blog/atom_feed', author=user.username),
             'application/atom+xml', _(u'All posts written by %s') %
             user.display_name)

    return render_response('show_author.html', user=user, **data)
Example #5
0
def show_category(req, slug, page=1):
    """Show all posts categoryged with a given category slug.

    Available template variables:

        `posts`:
            a list of post objects we want to display

        `pagination`:
            a pagination object to render a pagination

        `category`
            the category object for this page

    :Template name: ``show_category.html``
    :URL endpoint: ``blog/show_category``
    """
    category = Category.query.filter_by(slug=slug).first(True)
    per_page = req.app.theme.settings['category.per_page']
    data = category.posts.theme_lightweight('category') \
                   .published().get_list(page=page, per_page=per_page,
                                         endpoint='blog/show_category',
                                         url_args=dict(slug=slug))

    add_link('alternate', url_for('blog/atom_feed', category=slug),
             'application/atom+xml', _(u'All posts in category %s') % category.name)
    return render_response('show_category.html', category=category, **data)
Example #6
0
def archive(req, year=None, month=None, day=None, page=1):
    """Render the monthly archives.

    Available template variables:

        `posts`:
            a list of post objects we want to display

        `pagination`:
            a pagination object to render a pagination

        `year` / `month` / `day`:
            integers or None, useful to entitle the page

    :Template name: ``archive.html``
    :URL endpoint: ``blog/archive``
    """
    if not year:
        return render_response('archive.html', month_list=True,
                               **Post.query.published().for_index()
                                     .get_archive_summary())

    url_args = dict(year=year, month=month, day=day)
    per_page = req.app.theme.settings['archive.per_page']
    data = Post.query.theme_lightweight('archive_overview') \
               .published().for_index().date_filter(year, month, day) \
               .get_list(page=page, endpoint='blog/archive',
                         url_args=url_args, per_page=per_page)

    add_link('alternate', url_for('blog/atom_feed', **url_args),
             'application/atom+xml', _(u'Recent Posts Feed'))

    return render_response('archive.html', year=year, month=month, day=day,
                           date=date(year, month or 1, day or 1),
                           month_list=False, **data)
Example #7
0
def show_author(req, username, page=1):
    """Show the user profile of an author / editor or administrator.

    Available template variables:

        `posts`:
            a list of post objects this author wrote and are
            visible on this page

        `pagination`:
            a pagination object to render a pagination

        `user`
            the user object for this author

    :Template name: ``show_author.html``
    :URL endpoint: ``blog/show_author``
    """
    user = User.query.filter_by(username=username).first()
    if user is None or not user.is_author:
        raise NotFound()

    per_page = req.app.theme.settings['author.per_page']
    data = user.posts.theme_lightweight('author').published() \
                     .get_list(page=page, per_page=per_page,
                               endpoint='blog/show_author',
                               url_args=dict(username=user.username))

    add_link('alternate', url_for('blog/atom_feed', author=user.username),
             'application/atom+xml', _(u'All posts written by %s') %
             user.display_name)

    return render_response('show_author.html', user=user, **data)
Example #8
0
def show_tag(req, slug, page=1):
    """Show all posts categoryged with a given tag slug.

    Available template variables:

        `posts`:
            a list of post objects we want to display

        `pagination`:
            a pagination object to render a pagination

        `tag`
            the tag object for this page

    :Template name: ``show_tag.html``
    :URL endpoint: ``blog/show_tag``
    """
    tag = Tag.query.filter_by(slug=slug).first(True)
    per_page = req.app.theme.settings['tag.per_page']
    data = tag.posts.theme_lightweight('tag') \
                    .published().get_list(page=page, endpoint='blog/show_tag',
                                          per_page=per_page,
                                          url_args=dict(slug=slug))

    add_link('alternate', url_for('blog/atom_feed', tag=slug),
             'application/atom+xml', _(u'All posts tagged %s') % tag.name)
    return render_response('show_tag.html', tag=tag, **data)
Example #9
0
def archive(req, year=None, month=None, day=None, page=1):
    """Render the monthly archives.

    Available template variables:

        `posts`:
            a list of post objects we want to display

        `pagination`:
            a pagination object to render a pagination

        `year` / `month` / `day`:
            integers or None, useful to entitle the page.

    :Template name: ``archive.html``
    :URL endpoint: ``blog/archive``
    """
    if not year:
        return render_response('archive.html', month_list=True,
                               **Post.query.published().for_index()
                                     .get_archive_summary())

    url_args = dict(year=year, month=month, day=day)
    per_page = req.app.theme.settings['archive.per_page']
    data = Post.query.theme_lightweight('archive_overview') \
               .published().for_index().date_filter(year, month, day) \
               .get_list(page=page, endpoint='blog/archive',
                         url_args=url_args, per_page=per_page)

    add_link('alternate', url_for('blog/atom_feed', **url_args),
             'application/atom+xml', _(u'Recent Posts Feed'))

    return render_response('archive.html', year=year, month=month, day=day,
                           date=date(year, month or 1, day or 1),
                           month_list=False, **data)
Example #10
0
def redirect_back(*args, **kwargs):
    """Redirect back to the page we are comming from or the URL
    rule given.
    """
    target = get_redirect_target()
    if target is None:
        target = url_for(*args, **kwargs)
    # call werkzeug's redirect directly and not the redirect() function
    # from this module because it will strip leading slashes this function
    # returns and thus generate wrong redirects.
    return _redirect(target)
Example #11
0
def redirect_back(*args, **kwargs):
    """Redirect back to the page we are comming from or the URL
    rule given.
    """
    target = get_redirect_target()
    if target is None:
        target = url_for(*args, **kwargs)
    # call werkzeug's redirect directly and not the redirect() function
    # from this module because it will strip leading slashes this function
    # returns and thus generate wrong redirects.
    return _redirect(target)
Example #12
0
def list_documented_plugins(app):
    """Return a list of all documented plugins."""
    plugins = []
    for plugin in app.plugins.itervalues():
        if plugin.is_documented:
            plugins.append(
                '<li><a href="%s">%s</a></li>' %
                (url_for('admin/help', page='plugins/%s/' % plugin.name),
                 escape(plugin.display_name)))
    if not plugins:
        return u'<ul><li>%s</li></ul>' % _('no documented plugins installed.')
    return '<ul>%s</ul>' % '\n'.join(plugins)
Example #13
0
def list_documented_plugins(app):
    """Return a list of all documented plugins."""
    plugins = []
    for plugin in app.plugins.itervalues():
        if plugin.is_documented:
            plugins.append('<li><a href="%s">%s</a></li>' % (
                url_for('admin/help', page='plugins/%s/' % plugin.name),
                escape(plugin.display_name)
            ))
    if not plugins:
        return u'<ul><li>%s</li></ul>' % _('no documented plugins installed.')
    return '<ul>%s</ul>' % '\n'.join(plugins)
Example #14
0
 def find_urls(self):
     """Iterate over all urls in the text.  This will only work if the
     parser for this post is available, otherwise an exception is raised.
     The URLs returned are absolute URLs.
     """
     from zine.parsers import parse
     if self.parser_missing:
         raise TypeError('parser is missing, urls cannot be looked up.')
     found = set()
     this_url = url_for(self, _external=True)
     tree = parse(self.text, self.parser, 'linksearch')
     for node in tree.query('a[href]'):
         href = urljoin(this_url, node.attributes['href'])
         if href not in found:
             found.add(href)
             yield href
Example #15
0
 def find_urls(self):
     """Iterate over all urls in the text.  This will only work if the
     parser for this post is available, otherwise an exception is raised.
     The URLs returned are absolute URLs.
     """
     from zine.parsers import parse
     if self.parser_missing:
         raise TypeError('parser is missing, urls cannot be looked up.')
     found = set()
     this_url = url_for(self, _external=True)
     tree = parse(self.text, self.parser, 'linksearch')
     for node in tree.query('a[href]'):
         href = urljoin(this_url, node.attributes['href'])
         if href not in found:
             found.add(href)
             yield href
Example #16
0
def render_query_table(queries):
    """Renders a nice table of all queries in the page."""
    total = 0
    stylesheet = url_for('core/shared', filename='debug.css')
    result = [
        u'<style type="text/css">@import url(%s)</style>' % stylesheet,
        u'<div class="_database_debug_table"><ul>'
    ]
    for statement, parameters, start, end, calling_context in queries:
        total += (end - start)
        result.append(u'<li><pre>%s</pre><div class="detail"><em>%s</em> | '
                      u'<strong>took %.3f ms</strong></div></li>' %
                      (statement, escape(calling_context),
                       (end - start) * 1000))
    result.append(u'<li><strong>%d queries in %.2f ms</strong></ul></div>' %
                  (len(queries), total * 1000))
    return u'\n'.join(result)
Example #17
0
def render_query_table(queries):
    """Renders a nice table of all queries in the page."""
    total = 0
    stylesheet = url_for('core/shared', filename='debug.css')
    result = [u'<style type="text/css">@import url(%s)</style>' % stylesheet,
              u'<div class="_database_debug_table"><ul>']
    for statement, parameters, start, end, calling_context in queries:
        total += (end - start)
        result.append(u'<li><pre>%s</pre><div class="detail"><em>%s</em> | '
                      u'<strong>took %.3f ms</strong></div></li>' % (
            statement,
            escape(calling_context),
            (end - start) * 1000
        ))
    result.append(u'<li><strong>%d queries in %.2f ms</strong></ul></div>' % (
        len(queries),
        total * 1000
    ))
    return u'\n'.join(result)
Example #18
0
def index(req, page=1):
    """Render the most recent posts.

    Available template variables:

        `posts`:
            a list of post objects we want to display

        `pagination`:
            a pagination object to render a pagination

    :Template name: ``index.html``
    :URL endpoint: ``blog/index``
    """
    data = Post.query.published().for_index().get_list(endpoint='blog/index',
                                                       page=page)

    add_link('alternate', url_for('blog/atom_feed'), 'application/atom+xml',
             _(u'Recent Posts Feed'))
    return render_response('index.html', **data)
Example #19
0
def index(req, page=1):
    """Render the most recent posts.

    Available template variables:

        `posts`:
            a list of post objects we want to display

        `pagination`:
            a pagination object to render a pagination

    :Template name: ``index.html``
    :URL endpoint: ``blog/index``
    """
    data = Post.query.theme_lightweight('index').published() \
               .for_index().get_list(endpoint='blog/index',
                                     page=page)

    add_link('alternate', url_for('blog/atom_feed'), 'application/atom+xml',
             _(u'Recent Posts Feed'))
    return render_response('index.html', **data)
Example #20
0
 def get_url_values(self):
     return url_for(self.post) + '#comment-%d' % self.id
Example #21
0
 def get_url_values(self):
     return url_for(self.post) + '#comment-%d' % self.id
Example #22
0
def redirect_to(*args, **kwargs):
    """Temporarily redirect to an URL rule."""
    # call werkzeug's redirect directly and not the redirect() function
    # from this module because it will strip leading slashes this function
    # returns and thus generate wrong redirects.
    return _redirect(url_for(*args, **kwargs))
Example #23
0
def populate_feed(req, feed, author=None, year=None, month=None, day=None,
              category=None, tag=None, post=None):
    """Renders an atom feed requested.

    :URL endpoint: ``blog/atom_feed``
    """
    # the feed only contains published items
    query = Post.query.lightweight(lazy=('comments',)).published()

    # feed for a category
    if category is not None:
        category = Category.query.filter_by(slug=category).first(True)
        query = query.filter(Post.categories.contains(category))

    # feed for a tag
    if tag is not None:
        tag = Tag.query.filter_by(slug=tag).first(True)
        query = query.filter(Post.tags.contains(tag))

    # feed for an author
    if author is not None:
        author = User.query.filter_by(username=author).first(True)
        query = query.filter(Post.author == author)

    # feed for dates
    if year is not None:
        query = query.for_index().date_filter(year, month, day)

    # if no post slug is given we filter the posts by the cretereons
    # provided and pass them to the feed builder.  This will only return
    # a feed for posts with a content type listed in `index_content_types`
    if post is None:
        for post in query.for_index().order_by(Post.pub_date.desc()) \
                         .limit(15).all():
            alt_title = '%s @ %s' % (post.author.display_name, post.pub_date)
            feed.add_item(post.title or alt_title,
                          url_for(post, _external=True), unicode(post.body),
                          author_name=post.author.display_name,
                          pubdate=post.pub_date, unique_id=post.uid)

    # otherwise we create a feed for all the comments of a post.
    # the function is called this way by `dispatch_content_type`.
    else:
        comment_num = 1
        for comment in post.comments:
            if not comment.visible:
                continue
            uid = build_tag_uri(req.app, comment.pub_date, 'comment',
                                comment.id)
            title = _(u'Comment %(num)d on %(post)s') % {
                'num':  comment_num,
                'post': post.title
            }
            author = {'name': comment.author}
            if comment.www:
                author['uri'] = comment.www
            feed.add_item(title, url_for(comment, _external=True),
                          unicode(comment.body), author_name=author,
                          pubdate=comment.pub_date, unique_id=uid)
            comment_num += 1

    return feed.writeString('utf-8')
Example #24
0
def redirect_to(*args, **kwargs):
    """Temporarily redirect to an URL rule."""
    # call werkzeug's redirect directly and not the redirect() function
    # from this module because it will strip leading slashes this function
    # returns and thus generate wrong redirects.
    return _redirect(url_for(*args, **kwargs))
Example #25
0
    def generate(self, **options):
        """This method generates the pagination.  It accepts some
        keyword arguments that override the theme pagination settings.
        These arguments have the same name as the theme setting variables
        without the `pagination.` prefix.
        """
        from zine.application import url_for, get_application, \
             DEFAULT_THEME_SETTINGS

        if self._skip_theme_defaults:
            settings = DEFAULT_THEME_SETTINGS
        else:
            settings = get_application().theme.settings

        def _getopt(name):
            value = options.pop(name, None)
            if value is not None:
                return value
            return settings['pagination.' + name]
        normal = _getopt('normal')
        active = _getopt('active')
        commata = _getopt('commata')
        ellipsis = _getopt('ellipsis')
        threshold = _getopt('threshold')
        left_threshold = _getopt('left_threshold')
        right_threshold = _getopt('right_threshold')
        prev_link = _getopt('prev_link')
        next_link = _getopt('next_link')
        gray_prev_link = _getopt('gray_prev_link')
        gray_next_link = _getopt('gray_next_link')
        simple = _getopt('simple')
        if options:
            raise TypeError('generate() got an unexpected keyword '
                            'argument %r' % iter(options).next())

        was_ellipsis = False
        result = []
        prev = None
        next = None
        get_link = lambda x: url_for(self.endpoint, page=x,
                                     per_page=self.per_page,
                                     post_id=self.post_id, **self.url_args)

        if simple:
            result.append(active % {
                'url':      get_link(self.page),
                'page':     self.page
            })
            if self.page > 1:
                prev = self.page - 1
            if self.page < self.pages:
                next = self.page + 1
        else:
            for num in xrange(1, self.pages + 1):
                if num == self.page:
                    was_ellipsis = False
                if num - 1 == self.page:
                    next = num
                if num + 1 == self.page:
                    prev = num
                if num <= left_threshold or \
                   num > self.pages - right_threshold or \
                   abs(self.page - num) < threshold:
                    if result and result[-1] != ellipsis:
                        result.append(commata)
                    link = get_link(num)
                    template = num == self.page and active or normal
                    result.append(template % {
                        'url':      link,
                        'page':     num
                    })
                elif not was_ellipsis:
                    was_ellipsis = True
                    result.append(ellipsis)

        if next_link:
            if next is not None:
                result.append(u' <a href="%s" class="next">%s</a>' %
                              (get_link(next), _(u'Next »')))
            elif gray_next_link:
                result.append(u' <span class="disabled next">%s</span>' %
                              _(u'Next »'))
        if prev_link:
            if prev is not None:
                result.insert(0, u'<a href="%s" class="prev">%s</a> ' %
                              (get_link(prev), _(u'« Previous')))
            elif gray_prev_link:
                result.insert(0, u'<span class="disabled prev">%s</span> ' %
                              _(u'« Previous'))

        return u''.join(result)
Example #26
0
def atom_feed(req, author=None, year=None, month=None, day=None,
              category=None, tag=None, post=None):
    """Renders an atom feed requested.

    :URL endpoint: ``blog/atom_feed``
    """
    feed = AtomFeed(req.app.cfg['blog_title'], feed_url=req.url,
                    url=req.app.cfg['blog_url'],
                    subtitle=req.app.cfg['blog_tagline'])

    # the feed only contains published items
    query = Post.query.published()

    # feed for a category
    if category is not None:
        category = Category.query.filter_by(slug=category).first(True)
        query = query.filter(Post.categories.contains(category))

    # feed for a tag
    if tag is not None:
        tag = Tag.query.filter_by(slug=tag).first(True)
        query = query.filter(Post.tags.contains(tag))

    # feed for an author
    if author is not None:
        author = User.query.filter_by(username=author).first(True)
        query = query.filter(Post.author == author)

    # feed for dates
    if year is not None:
        query = query.for_index().date_filter(year, month, day)

    # if no post slug is given we filter the posts by the cretereons
    # provided and pass them to the feed builder.  This will only return
    # a feed for posts with a content type listed in `index_content_types`
    if post is None:
        for post in query.for_index().order_by(Post.pub_date.desc()) \
                         .limit(15).all():
            links = [link.as_dict() for link in post.links]
            feed.add(post.title or '%s @ %s' % (post.author.display_name,
                     post.pub_date), unicode(post.body), content_type='html',
                     author=post.author.display_name, links=links,
                     url=url_for(post, _external=True), id=post.uid,
                     updated=post.last_update, published=post.pub_date)

    # otherwise we create a feed for all the comments of a post.
    # the function is called this way by `dispatch_content_type`.
    else:
        comment_num = 1
        for comment in post.comments:
            if not comment.visible:
                continue
            uid = build_tag_uri(req.app, comment.pub_date, 'comment',
                                comment.id)
            title = _(u'Comment %(num)d on %(post)s') % {
                'num':  comment_num,
                'post': post.title
            }
            author = {'name': comment.author}
            if comment.www:
                author['uri'] = comment.www
            feed.add(title, unicode(comment.body), content_type='html',
                     author=author, url=url_for(comment, _external=True),
                     id=uid, updated=comment.pub_date)
            comment_num += 1

    return feed.get_response()