def change_comment(self, request, id, action): comment = Comment.query.get(id) if action in ('hide', 'restore'): message = { 'hide': _(u'Do you really want to hide the comment?'), 'restore': _(u'Do you really want to restore the comment?') } if confirm_action(request, message[action], 'news/edit_comment', id=id, action=action): comment.deleted = action == 'hide' db.session.commit() request.flash(_(u'The comment has been hidden') if \ action == 'hide' else _(u'The comment has been restored')) return redirect_to(comment) return redirect_to(comment.article) # action == 'edit' form = EditCommentForm(request.form) if form.validate_on_submit(): if form.validate(): comment.text = form.text.data db.session.commit() request.flash(_(u'The comment was saved'), True) return redirect_to(comment) else: form.text.data = comment.text return { 'comment': comment, 'form': form, }
def detail(self, request, slug): article = Article.query.filter_by(slug=slug).one() if article.hidden: #TODO: ACL Check request.flash(_(u'This article is hidden'), False) if article.comments_enabled: form = EditCommentForm(request.form) if form.validate_on_submit(): if form.data.get('comment_id', None): comment = Comment.query.get(form.comment_id.data) comment.text = form.text.data request.flash(_(u'The comment was successfully edited'), True) else: comment = Comment(text=form.text.data, author=request.user) article.comments.append(comment) Subscription.new(comment, 'news.comment.new') request.flash(_(u'Your comment was successfully created'), True) db.session.commit() return redirect_to(comment) else: form = EditCommentForm() # increase counters article.touch() comments = list(article.comments.options(db.joinedload('author'))) Subscription.accessed(request.user, object=article, subject=article) return {'article': article, 'comments': comments, 'form': form}
def detail(self, request, slug): article = Article.query.filter_by(slug=slug).one() if article.hidden: # TODO: ACL Check request.flash(_(u"This article is hidden"), False) if article.comments_enabled: form = EditCommentForm(request.form) if form.validate_on_submit(): if form.data.get("comment_id", None): comment = Comment.query.get(form.comment_id.data) comment.text = form.text.data request.flash(_(u"The comment was successfully edited"), True) else: comment = Comment(text=form.text.data, author=request.user) article.comments.append(comment) Subscription.new(comment, "news.comment.new") request.flash(_(u"Your comment was successfully created"), True) db.session.commit() return redirect_to(comment) else: form = EditCommentForm() # increase counters article.touch() comments = list(article.comments.options(db.joinedload("author"))) Subscription.accessed(request.user, object=article, subject=article) return {"article": article, "comments": comments, "form": form}
def change_comment(self, request, id, action): comment = Comment.query.get(id) if action in ("hide", "restore"): message = { "hide": _(u"Do you really want to hide the comment?"), "restore": _(u"Do you really want to restore the comment?"), } if confirm_action(request, message[action], "news/edit_comment", id=id, action=action): comment.deleted = action == "hide" db.session.commit() request.flash( _(u"The comment has been hidden") if action == "hide" else _(u"The comment has been restored") ) return redirect_to(comment) return redirect_to(comment.article) # action == 'edit' form = EditCommentForm(request.form) if form.validate_on_submit(): if form.validate(): comment.text = form.text.data db.session.commit() request.flash(_(u"The comment was saved"), True) return redirect_to(comment) else: form.text.data = comment.text return {"comment": comment, "form": form}
def tags_delete(self, request, slug): message = _(u'Do you really want to delete this tag?') tag = Tag.query.filter_by(slug=slug).one() if confirm_action(request, message, 'portal/tag_delete', slug=slug): db.session.delete(tag) db.session.commit() request.flash(_(u'The tag “%s” was deleted successfully.' % tag.name)) return redirect_to('portal/tags') return redirect_to(tag)
def parse(markup, catch_stack_errors=True, transformers=None): """Parse markup into a node.""" try: return Parser(markup, transformers).parse() except StackExhaused: if not catch_stack_errors: raise return nodes.Paragraph([ nodes.Strong([nodes.Text(_(u'Internal parser error: '))]), nodes.Text(_(u'The parser could not process the text because ' u'it exceeded the maximum allowed depth for nested ' u'elements')) ])
def parse(markup, catch_stack_errors=True, transformers=None): """Parse markup into a node.""" try: return Parser(markup, transformers).parse() except StackExhaused: if not catch_stack_errors: raise return nodes.Paragraph([ nodes.Strong([nodes.Text(_(u'Internal parser error: '))]), nodes.Text( _(u'The parser could not process the text because ' u'it exceeded the maximum allowed depth for nested ' u'elements')) ])
def articles_delete(self, request, slug): article = Article.query.filter_by(slug=slug).one() if 'cancel' in request.form: request.flash(_(u'Action canceled')) elif request.method in ('POST', 'PUT') and 'confirm' in request.form: db.session.delete(article) db.session.commit() request.flash(_(u'The article “%s” was deleted successfully.' % article.title)) return redirect_to('news/articles') else: request.flash(render_template('news/admin/article_delete.html', { 'article': article }), html=True) return redirect_to(article, action='edit')
def get_serializer(request_or_format): """Returns the serializer for the given API request.""" def _search_for_accepted(req): best_match = (None, 0) for mimetype, serializer in _serializer_for_mimetypes.iteritems(): quality = req.accept_mimetypes[mimetype] if quality > best_match[1]: best_match = (serializer, quality) if best_match[0] is None: raise BadRequest(_(u'Could not detect format. You have to specify ' u'the format as query argument or in the accept ' u'HTTP header.')) # special case. If the best match is not html and the quality of # text/html is the same as the best match, we prefer HTML. if best_match[0] != 'text/html' and \ best_match[1] == req.accept_mimetypes['text/html']: return _serializer_map['debug'] return _serializer_map[best_match[0]] if not isinstance(request_or_format, basestring): # we got no string so we assume that we got a proper # request object and search for the format. format = request_or_format.args.get('format') if format is not None: rv = _serializer_map.get(format) if rv is None: raise BadRequest(_(u'Unknown format "%s"') % escape(format)) return rv return _search_for_accepted(request_or_format) # we got a string so we assume we got a proper format applied. return _serializer_map[request_or_format]
def get_serializer(request_or_format): """Returns the serializer for the given API request.""" def _search_for_accepted(req): best_match = (None, 0) for mimetype, serializer in _serializer_for_mimetypes.iteritems(): quality = req.accept_mimetypes[mimetype] if quality > best_match[1]: best_match = (serializer, quality) if best_match[0] is None: raise BadRequest( _(u'Could not detect format. You have to specify ' u'the format as query argument or in the accept ' u'HTTP header.')) # special case. If the best match is not html and the quality of # text/html is the same as the best match, we prefer HTML. if best_match[0] != 'text/html' and \ best_match[1] == req.accept_mimetypes['text/html']: return _serializer_map['debug'] return _serializer_map[best_match[0]] if not isinstance(request_or_format, basestring): # we got no string so we assume that we got a proper # request object and search for the format. format = request_or_format.args.get('format') if format is not None: rv = _serializer_map.get(format) if rv is None: raise BadRequest(_(u'Unknown format "%s"') % escape(format)) return rv return _search_for_accepted(request_or_format) # we got a string so we assume we got a proper format applied. return _serializer_map[request_or_format]
def subscribe_comments(self, request, action, slug): do = {"subscribe": Subscription.subscribe, "unsubscribe": Subscription.unsubscribe}[action] article = Article.query.filter_by(slug=slug).one() existed = do(request.user, CommentSubscriptionType, article) msg = { "subscribe": [ _(u"You had already been subscribed before."), _(u"You have successfully been subscribed to " u"new comments on this article."), ], "unsubscribe": [ _(u"You had not been subscribed before."), _(u"You have successfully been unsubscribed from " u"new comments on this article."), ], } request.flash(msg[action][existed], True if not existed else None) return redirect_to(article)
def subscribe_articles(self, request, action): do = {"subscribe": Subscription.subscribe, "unsubscribe": Subscription.unsubscribe}[action] existed = do(request.user, ArticleSubscriptionType) msg = { "subscribe": [ _(u"You had already been subscribed before."), _(u"You have successfully been subscribed to " u"new News articles."), ], "unsubscribe": [ _(u"You had not been subscribed before."), _(u"You have successfully been unsubscribed from " u"new News articles."), ], } request.flash(msg[action][existed], True if not existed else None) return redirect_to("news/index")
def _get_pygments_lexers(add_empty=True): r = [] if add_empty: r.append((u'', u''), ) for lexer in get_all_lexers(): r.append((lexer[1][0], _(lexer[0])), ) r.sort(key=itemgetter(1)) return r
def _get_pygments_lexers(add_empty=True): r = [] if add_empty: r.append((u'', u''),) for lexer in get_all_lexers(): r.append((lexer[1][0], _(lexer[0])),) r.sort(key=itemgetter(1)) return r
def send_activation_mail(user_id, activation_url): user = User.query.get(user_id) website_title = ctx.cfg['website_title'] send_email(_(u'Registration at %s') % website_title, render_template('mails/registration', { 'user': user, 'activation_url': activation_url, 'website_title': website_title, }), ctx.cfg['mail_address'], user.email)
def send_activation_mail(user_id, activation_url): user = User.query.get(user_id) website_title = ctx.cfg['website_title'] send_email( _(u'Registration at %s') % website_title, render_template( 'mails/registration', { 'user': user, 'activation_url': activation_url, 'website_title': website_title, }), ctx.cfg['mail_address'], user.email)
def subscribe_comments(self, request, action, slug): do = { 'subscribe': Subscription.subscribe, 'unsubscribe': Subscription.unsubscribe, }[action] article = Article.query.filter_by(slug=slug).one() existed = do(request.user, CommentSubscriptionType, article) msg = { 'subscribe': [ _(u'You had already been subscribed before.'), _(u'You have successfully been subscribed to ' u'new comments on this article.') ], 'unsubscribe': [ _(u'You had not been subscribed before.'), _(u'You have successfully been unsubscribed from ' u'new comments on this article.') ], } request.flash(msg[action][existed], True if not existed else None) return redirect_to(article)
def subscribe_articles(self, request, action): do = { 'subscribe': Subscription.subscribe, 'unsubscribe': Subscription.unsubscribe, }[action] existed = do(request.user, ArticleSubscriptionType) msg = { 'subscribe': [ _(u'You had already been subscribed before.'), _(u'You have successfully been subscribed to ' u'new News articles.') ], 'unsubscribe': [ _(u'You had not been subscribed before.'), _(u'You have successfully been unsubscribed from ' u'new News articles.') ], } request.flash(msg[action][existed], True if not existed else None) return redirect_to('news/index')
def article_feed(self, request, slug=None): """ Shows all news entries that match the given criteria in an atom feed. """ query = Article.query title = u"News" if slug: # filter the articles matching a defined tag tag = Tag.query.public().filter_by(slug=slug).one() query = tag.articles title = _(u"News for %s" % slug) query = query.options(db.eagerload("author")).order_by(Article.updated.desc()).limit(20) feed = AtomFeed( _(u"%s – %s" % (title, ctx.cfg["website_title"])), feed_url=request.url, url=request.url_root, icon=href("static", file="img/favicon.ico"), ) for article in query.all(): value = u"%s\n%s" % ( article.get_rendered_text(article.intro, request, "html"), article.get_rendered_text(article.text, request, "html"), ) feed.add( article.title, value, content_type="html", url=href(article, _external=True), author={"name": article.author.display_name, "uri": href(article.author.profile)}, id=article.guid, updated=article.updated, published=article.pub_date, ) return feed
def article_feed(self, request, slug=None): """ Shows all news entries that match the given criteria in an atom feed. """ query = Article.query title = u'News' if slug: # filter the articles matching a defined tag tag = Tag.query.public().filter_by(slug=slug).one() query = tag.articles title = _(u'News for %s' % slug) query = query.options(db.eagerload('author')) \ .order_by(Article.updated.desc()).limit(20) feed = AtomFeed(_(u'%s – %s' % (title, ctx.cfg['website_title'])), feed_url=request.url, url=request.url_root, icon=href('static', file='img/favicon.ico')) for article in query.all(): value = u'%s\n%s' % ( article.get_rendered_text(article.intro, request, 'html'), article.get_rendered_text(article.text, request, 'html')) feed.add(article.title, value, content_type='html', url=href(article, _external=True), author={ 'name': article.author.display_name, 'uri': href(article.author.profile) }, id=article.guid, updated=article.updated, published=article.pub_date) return feed
class AddEventForm(Form): title = TextField(_(u'Title'), [validators.length(max=100), validators.required()]) text = TextField(_(u'Text'), [validators.required()], widget=widgets.TextArea()) start = DateTimeField(_(u'Start'), [validators.required()]) end = DateTimeField(_(u'End'), [validators.required()]) tags = AutocompleteField(_(u'Tags'), get_label='name', query_factory=lambda: Tag.query.autoflush(False)) discussion_question = BooleanField(_(u'Create topic for discussion')) info_question = BooleanField(_(u'Create topic for further information'))
def get_sorted(self): """Return a query object with the proper ordering applied.""" ocol = escape(self.order_by.lstrip('-')) if ocol not in self.columns.keys(): # safes us from some bad usage that raises an exception ctx.current_request.flash( _(u'The selected criterium “%s” is not available, ' u'falling back to default ordering') % ocol, html=True) self.order_by = self.default_col ocol = self.order_by.lstrip('-') if self.order_by is None: return self.query order = (db.asc, db.desc)[self.order_by.startswith('-')] return self.query.order_by(order(self.columns[ocol]))
def tags_edit(self, request, slug=None): new = slug is None if new: tag, data = Tag(), {} else: tag = Tag.query.filter_by(slug=slug).one() data = model_to_dict(tag, exclude=('slug')) form = EditTagForm(request.form, **data) if 'delete' in request.form: return redirect_to('portal/tag_delete', slug=tag.slug) elif form.validate_on_submit(): tag = update_model(tag, form, ('name')) db.session.commit() if new: request.flash(_(u'Created tag “%s”' % tag.name), True) else: request.flash(_(u'Updated tag “%s”' % tag.name), True) return { 'form': form, 'tag': tag, }
def articles_edit(self, request, slug=None): new = slug is None if new: article, data = Article(), {'tags': []} else: article = Article.query.filter_by(slug=slug).one() data = model_to_dict(article, exclude=('slug')) form = EditArticleForm(request.form, **data) if 'delete' in request.form: return redirect_to('news/article_delete', slug=article.slug) elif form.validate_on_submit(): article = update_model(article, form, ('pub_date', 'updated', 'title', 'intro', 'text', 'public', 'tags', 'author')) db.session.commit() msg = slug and _(u'Updated article “%s”') \ or _(u'Created article “%s”') request.flash(msg % article.title, True) return redirect_to(article) return { 'form': form, 'article': article, }
class EditArticleForm(Form): title = TextField(_(u'Title'), [validators.required(), validators.length(max=200)]) intro = TextField(_(u'Intro'), [validators.required()], widget=widgets.TextArea()) text = TextField(_(u'Text'), [validators.required()], widget=widgets.TextArea()) public = BooleanField(_(u'Published')) tags = AutocompleteField(_(u'Tags'), get_label='name', query_factory=lambda: Tag.query.autoflush(False)) author = QuerySelectField(_(u'Author'), [validators.required()], query_factory=lambda: User.query.autoflush(False), widget=widgets.Select())
def timedeltaformat(datetime_or_timedelta, threshold=.85, granularity='second'): """Special locale aware timedelta format function Usage Example:: >>> timedeltaformat(timedelta(weeks=12)) u'three mths ago' >>> timedeltaformat(timedelta(seconds=30)) u'30 secs ago' >>> timedeltaformat(timedelta(seconds=0)) u'just now' The granularity parameter can be provided to alter the lowest unit presented, which defaults to a second. >>> timedeltaformat(timedelta(hours=3), granularity='day') u'one day ago' The threshold parameter can be used to determine at which value the presentation switches to the next higher unit. A higher threshold factor means the presentation will switch later. For example: >>> timedeltaformat(timedelta(hours=23), threshold=0.9) u'one day ago' >>> timedeltaformat(timedelta(hours=23), threshold=1.1) u'23 hrs ago' :param datetime_or_timedelta: Either a datetime or timedelta object. If it's a datetime object we caclculate the timedelta from this object to now (using UTC) :param threshold: factor that determines at which point the presentation switches to the next higher unit :param granularity: determines the smallest unit that should be displayed, the value can be one of "year", "month", "week", "day", "hour", "minute" or "second" """ if isinstance(datetime_or_timedelta, datetime): datetime_or_timedelta = datetime.utcnow() - datetime_or_timedelta if datetime_or_timedelta <= timedelta(seconds=3): return _(u'just now') timedelta_ = _format_timedelta(datetime_or_timedelta, granularity, threshold=threshold) return lazy_gettext(u'%(timedelta)s ago') % {'timedelta': timedelta_}
def timedeltaformat(datetime_or_timedelta, threshold=0.85, granularity="second"): """Special locale aware timedelta format function Usage Example:: >>> timedeltaformat(timedelta(weeks=12)) u'three mths ago' >>> timedeltaformat(timedelta(seconds=30)) u'30 secs ago' >>> timedeltaformat(timedelta(seconds=0)) u'just now' The granularity parameter can be provided to alter the lowest unit presented, which defaults to a second. >>> timedeltaformat(timedelta(hours=3), granularity='day') u'one day ago' The threshold parameter can be used to determine at which value the presentation switches to the next higher unit. A higher threshold factor means the presentation will switch later. For example: >>> timedeltaformat(timedelta(hours=23), threshold=0.9) u'one day ago' >>> timedeltaformat(timedelta(hours=23), threshold=1.1) u'23 hrs ago' :param datetime_or_timedelta: Either a datetime or timedelta object. If it's a datetime object we caclculate the timedelta from this object to now (using UTC) :param threshold: factor that determines at which point the presentation switches to the next higher unit :param granularity: determines the smallest unit that should be displayed, the value can be one of "year", "month", "week", "day", "hour", "minute" or "second" """ if isinstance(datetime_or_timedelta, datetime): datetime_or_timedelta = datetime.utcnow() - datetime_or_timedelta if datetime_or_timedelta <= timedelta(seconds=3): return _(u"just now") timedelta_ = _format_timedelta(datetime_or_timedelta, granularity, threshold=threshold) return lazy_gettext(u"%(timedelta)s ago") % {"timedelta": timedelta_}
def _search_for_accepted(req): best_match = (None, 0) for mimetype, serializer in _serializer_for_mimetypes.iteritems(): quality = req.accept_mimetypes[mimetype] if quality > best_match[1]: best_match = (serializer, quality) if best_match[0] is None: raise BadRequest(_(u'Could not detect format. You have to specify ' u'the format as query argument or in the accept ' u'HTTP header.')) # special case. If the best match is not html and the quality of # text/html is the same as the best match, we prefer HTML. if best_match[0] != 'text/html' and \ best_match[1] == req.accept_mimetypes['text/html']: return _serializer_map['debug'] return _serializer_map[best_match[0]]
def as_message(self): """Return the email as MIMEText object.""" if not self.subject or not self.text or not self.to_addrs: raise RuntimeError(_(u'Not all mailing parameters filled in')) msg = MIMEText(self.text.encode('utf-8')) #: MIMEText sucks, it does not override the values on #: setitem, it appends them. We get rid of some that #: are predefined under some versions of python del msg['Content-Transfer-Encoding'] del msg['Content-Type'] msg['From'] = self.from_addr.encode('utf-8') msg['To'] = ', '.join(x.encode('utf-8') for x in self.to_addrs) msg['Subject'] = self.subject.encode('utf-8') msg['Content-Transfer-Encoding'] = '8bit' msg['Content-Type'] = 'text/plain; charset=utf-8' return msg
def _search_for_accepted(req): best_match = (None, 0) for mimetype, serializer in _serializer_for_mimetypes.iteritems(): quality = req.accept_mimetypes[mimetype] if quality > best_match[1]: best_match = (serializer, quality) if best_match[0] is None: raise BadRequest( _(u'Could not detect format. You have to specify ' u'the format as query argument or in the accept ' u'HTTP header.')) # special case. If the best match is not html and the quality of # text/html is the same as the best match, we prefer HTML. if best_match[0] != 'text/html' and \ best_match[1] == req.accept_mimetypes['text/html']: return _serializer_map['debug'] return _serializer_map[best_match[0]]
def add_addr(self, addr): """Add an mail address to the list of recipients""" lines = addr.splitlines() if len(lines) != 1: raise ValueError(_(u'invalid value for email address')) self.to_addrs.append(lines[0])
def decorated(*args, **kwargs): if ctx.current_request.user.is_anonymous: ctx.current_request.flash(_(u'You must login to view this!')) return redirect_to('portal/login', _next=ctx.current_request.url) return func(*args, **kwargs)
""" import random from datetime import datetime from werkzeug import cached_property from inyoka.i18n import _ from inyoka.core.cache import cache from inyoka.context import ctx from inyoka.core.database import db from inyoka.core.serializer import SerializableObject from inyoka.core.subscriptions import subscribed from inyoka.utils.datastructures import BidiMap from inyoka.utils.crypt import get_hexdigest USER_STATUS_MAP = BidiMap({ 0: _(u'inactive'), #not yet activated 1: _(u'normal'), 2: _(u'banned'), 3: _(u'deleted'), #deleted itself }) group_group = db.Table( 'core_group_group', db.metadata, db.Column('group_id', db.Integer, db.ForeignKey('core_group.id')), db.Column('parent_id', db.Integer, db.ForeignKey('core_group.id')), ) user_group = db.Table( 'core_group_user', db.metadata, db.Column('user_id', db.Integer, db.ForeignKey('core_user.id')),
class EditPasteForm(AddPasteForm): hidden = BooleanField(_(u'Hide Paste'))
class AddPasteForm(Form): title = TextField(_(u'Title (optional)'), [validators.length(max=50)]) text = TextField(_(u'Text'), [validators.required()], widget=widgets.TextArea()) language = SelectField(_(u'Language'), choices=_get_pygments_lexers()) parent = HiddenIntegerField(validators=[validators.optional()])
def humanize_number(number): """Format numbers from 0 to 12 to strings. unfortunately, this cannot be done with Babel. Usage Example:: >>> humanize_number(6) u'six' >>> humanize_number(13) u'13' >>> humanize_number(u'some_string') u'some_string' """ strings = [ _(u"zero"), _(u"one"), _(u"two"), _(u"three"), _(u"four"), _(u"five"), _(u"six"), _(u"seven"), _(u"eight"), _(u"nine"), _(u"ten"), _(u"eleven"), _(u"twelve"), ] return strings[number] if number in xrange(13) else unicode(number)
class Pagination(object): """ :param query: A SQLAlchemy query object. :param page: The page number. :param link: The base link for the pagination. If it is not supplied, relative links are used instead. :param args: URL parameters, that, if given, are included in the generated urls. :param per_page: Number of entries displayed on one page. After initialisation, ``pagination.query`` is a list of the matching objects. Call the pagination object for html code of links to the other pages. """ # translatable strings for the pagination buttons _comma = u'<span class="comma">%s</span>' % escape(_(u', ')) _next = escape(_(u'next »')) _prev = escape(_(u'« previous')) _ellipsis = escape(_(u'…')) # defaults left_threshold = 2 inner_threshold = 1 right_threshold = 1 per_page = 15 def __init__(self, query, page=None, link=None, args=None, per_page=None): self.base_query = query self.page = 1 if page is None else page if link is not None and not isinstance(link, basestring): link = link() self.link = link self.args = {} if args is None else args if per_page is not None: self.per_page = per_page #TODO: implement position_col self.total = self.base_query.count() self.pages = (max(0, self.total - 1) // self.per_page) + 1 if self.page > self.pages or self.page < 1: raise NotFound() offset = (self.page - 1) * self.per_page #TODO: implement position_col self.query = query[offset:offset + self.per_page] @abstract def make_link(self, page): """ Create a link to the given page. Usually used internally only. Subclasses must implement this. """ def make_template(self): """ Return a template for creating links. Usually used internally only. The template must contain a ``!`` at the place where the page number is to be inserted. This is used by JavaScript. Subclasses may implement this to enable a JavaScript page selector. """ return None def _get_buttons(self, left_threshold=None, inner_threshold=None, right_threshold=None, prev=True, next=True): """ Return the buttons as tuples. First item is page number or one of prev, next, ellipsis. Second item is link or None if it's the current page or (for prev/next) if it's the first or last page This is split into a separate method to ease unittesting. """ if left_threshold is None: left_threshold = self.left_threshold if inner_threshold is None: inner_threshold = self.inner_threshold if right_threshold is None: right_threshold = self.right_threshold def include(num, avoidsingle=True): if num < 1 or num > self.pages: return False if num < (left_threshold + 1): return True if num < self.page and num >= (self.page - inner_threshold): return True if num == self.page: return True if num > self.page and num <= (self.page + inner_threshold): return True if num > (self.pages - right_threshold): return True # avoid 4 ... 6 if avoidsingle: if include(num + 1, False) and include(num - 1, False): return True return False if prev: if self.page == 1: yield 'prev', None else: yield 'prev', self.make_link(self.page - 1) was_ellipsis = False for num in xrange(1, self.pages + 1): if include(num): if num == self.page: yield num, None else: yield num, self.make_link(num) was_ellipsis = False else: if not was_ellipsis: yield 'ellipsis', self.make_template() was_ellipsis = True if next: if self.page == self.pages: yield 'next', None else: yield 'next', self.make_link(self.page + 1) def buttons(self, left_threshold=None, inner_threshold=None, right_threshold=None, prev=True, next=True, class_=u'pagination', force=False): """ Return HTML code for the page selector if there is more than one page. For convenience, the ``__call__`` method is an alias for this. :param left_threshold: The number of pages to be shown after the `prev` button. :param inner_threshold: The number of pages to be shown before and after the current page. :param right_threshold: The number of pages to be shown before the `next` button. :param prev: If False, do not show an extra link to the previous page. :param next: If False, do not show an extra link to the next page. :param class_: The class attribute for the enclosing `div` element. Defaults to `pagination`. :param force: If True, return buttons even if there is only one page. """ if self.pages == 1 and not force: return Markup(u'') ret = [] add = ret.append add(u'<div class="%s">' % class_) # no comma at beginning was_ellipsis = True for type, link in self._get_buttons(left_threshold=left_threshold, inner_threshold=inner_threshold, right_threshold=right_threshold, prev=prev, next=next): if type == 'ellipsis': add(u' <span class="ellipsis">%s</span> ' % self._ellipsis) if link: add(u'<input type="hidden" class="url-template" value="%s">' % escape(link)) was_ellipsis = True continue if not was_ellipsis: add(self._comma) was_ellipsis = False if type == 'prev': if link: add(u'<a href="%s" class="prev">%s</a>' % (escape(link), self._prev)) else: add(u'<span class="prev disabled">%s</span>' % self._prev) elif type == 'next': if link: add(u'<a href="%s" class="next">%s</a>' % (escape(link), self._next)) else: add(u'<span class="next disabled">%s</span>' % self._next) else: _pageclass = ' page1' if type == 1 else '' # required for JS if link: add(u'<a href="%s" class="page%s">%d</a>' % (escape(link), _pageclass, type)) else: add(u'<strong class="page%s">%d</strong>' % (_pageclass, type)) add(u'</div>') return Markup(u''.join(ret)) def __call__(self, *args, **kwargs): """Alias for :meth:`buttons()`.""" return self.buttons(*args, **kwargs)
def humanize_number(number): """Format numbers from 0 to 12 to strings. unfortunately, this cannot be done with Babel. Usage Example:: >>> humanize_number(6) u'six' >>> humanize_number(13) u'13' >>> humanize_number(u'some_string') u'some_string' """ strings = [_(u'zero'), _(u'one'), _(u'two'), _(u'three'), _(u'four'), _(u'five'), _(u'six'), _(u'seven'), _(u'eight'), _(u'nine'), _(u'ten'), _(u'eleven'), _(u'twelve')] return strings[number] if number in xrange(13) else unicode(number)
import random from datetime import datetime from werkzeug import cached_property from inyoka.i18n import _ from inyoka.core.cache import cache from inyoka.context import ctx from inyoka.core.database import db from inyoka.core.serializer import SerializableObject from inyoka.core.subscriptions import subscribed from inyoka.utils.datastructures import BidiMap from inyoka.utils.crypt import get_hexdigest USER_STATUS_MAP = BidiMap({ 0: _(u'inactive'), #not yet activated 1: _(u'normal'), 2: _(u'banned'), 3: _(u'deleted'), #deleted itself }) group_group = db.Table('core_group_group', db.metadata, db.Column('group_id', db.Integer, db.ForeignKey('core_group.id')), db.Column('parent_id', db.Integer, db.ForeignKey('core_group.id')), ) user_group = db.Table('core_group_user', db.metadata, db.Column('user_id', db.Integer, db.ForeignKey('core_user.id')), db.Column('group_id', db.Integer, db.ForeignKey('core_group.id')) )
class EditCommentForm(Form): text = TextField(_(u'Text'), widget=widgets.TextArea(), description=Markup(_(u'To quote another comment use ' u'<em>@comment_number</em>. This is ' u'automatically used if you click “answer”.')))
class EMail(object): """Represents one E-Mail message that can be sent.""" def __init__(self, subject=None, text='', to_addrs=None): self.subject = u' '.join(subject.splitlines()) self.text = text from_addr = ctx.cfg['email.system_email'] self.from_addr = u'%s <%s>' % (ctx.cfg['website_title'], from_addr) self.to_addrs = [] if isinstance(to_addrs, basestring): self.add_addr(to_addrs) else: for addr in to_addrs: self.add_addr(addr) def add_addr(self, addr): """Add an mail address to the list of recipients""" lines = addr.splitlines() if len(lines) != 1: raise ValueError(_(u'invalid value for email address')) self.to_addrs.append(lines[0]) def as_message(self): """Return the email as MIMEText object.""" if not self.subject or not self.text or not self.to_addrs: raise RuntimeError(_(u'Not all mailing parameters filled in')) msg = MIMEText(self.text.encode('utf-8')) #: MIMEText sucks, it does not override the values on #: setitem, it appends them. We get rid of some that #: are predefined under some versions of python del msg['Content-Transfer-Encoding'] del msg['Content-Type'] msg['From'] = self.from_addr.encode('utf-8') msg['To'] = ', '.join(x.encode('utf-8') for x in self.to_addrs) msg['Subject'] = self.subject.encode('utf-8') msg['Content-Transfer-Encoding'] = '8bit' msg['Content-Type'] = 'text/plain; charset=utf-8' return msg def format(self, sep='\r\n'): """Format the message into a string.""" return sep.join(self.as_message().as_string().splitlines()) def log(self): """Logs the email""" logger.debug('%s\n%s\n\n' % ('-' * 79, self.format('\n').rstrip())) if ctx.cfg['testing']: outbox.append(self.as_message().as_string()) def send(self): """Send the message.""" try: smtp = SMTP(ctx.cfg['email.smtp_host'], ctx.cfg['email.smtp_port']) except SMTPException, e: raise RuntimeError(str(e)) if ctx.cfg['email.smtp_use_tls']: smtp.ehlo() if not smtp.esmtp_features.has_key('starttls'): raise RuntimeError( _(u'TLS enabled but server does not ' u'support TLS')) smtp.starttls() smtp.ehlo() if ctx.cfg['email.smtp_user']: try: smtp.login(ctx.cfg['email.smtp_user'], ctx.cfg['email.smtp_password']) except SMTPException, e: raise RuntimeError(str(e))