[geany/www.geany.org] 29d0f2: PEP8 cleanup
Enrico Tröger
git-noreply at xxxxx
Sat May 11 13:15:54 UTC 2019
Branch: refs/heads/master
Author: Enrico Tröger <enrico.troeger at uvena.de>
Committer: Enrico Tröger <enrico.troeger at uvena.de>
Date: Sun, 31 Mar 2019 21:47:58 UTC
Commit: 29d0f2933ceb55fedb0804f123f11d1ad008e17f
https://github.com/geany/www.geany.org/commit/29d0f2933ceb55fedb0804f123f11d1ad008e17f
Log Message:
-----------
PEP8 cleanup
Modified Paths:
--------------
geany/apps.py
geany/decorators.py
geany/hosts.py
geany/management/commands/dump_database.py
geany/settings.py
geany/sitemaps.py
geany/templatetags/geany_tags.py
geany/urls.py
geany/wsgi.py
latest_version/admin.py
latest_version/context_processors.py
latest_version/models.py
latest_version/urls.py
news/admin.py
news/feeds.py
news/models.py
news/sitemaps.py
news/templatetags/news_tags.py
news/urls.py
news/views.py
nightlybuilds/database_routers.py
nightlybuilds/models.py
nightlybuilds/templatetags/nightlybuilds_tags.py
nightlybuilds/urls.py
nightlybuilds/views.py
pastebin/admin.py
pastebin/api/create.py
pastebin/forms.py
pastebin/highlight.py
pastebin/management/commands/cleanup_snippets.py
pastebin/management/commands/generate_snippets_css.py
pastebin/models.py
pastebin/templatetags/pastebin_tags.py
pastebin/urls.py
pastebin/views.py
static_docs/generate_i18n_statistics.py
static_docs/github_client.py
static_docs/management/commands/generate_i18n_statistics.py
static_docs/urls.py
static_docs/views.py
Modified: geany/apps.py
1 lines changed, 0 insertions(+), 1 deletions(-)
===================================================================
@@ -15,7 +15,6 @@
from django.apps import AppConfig
-########################################################################
class GeanyAppConfig(AppConfig):
name = 'geany'
verbose_name = "Geany"
Modified: geany/decorators.py
17 lines changed, 10 insertions(+), 7 deletions(-)
===================================================================
@@ -5,32 +5,35 @@
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
-#
+#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
-#
+#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
from binascii import hexlify
-from django.core.cache import cache as _djcache
import inspect
+from django.core.cache import cache as _djcache
+
CACHE_TIMEOUT_24HOURS = 3600 * 24
CACHE_TIMEOUT_1HOUR = 3600
-#----------------------------------------------------------------------
+# ----------------------------------------------------------------------
def cache_function(timeout=900, ignore_arguments=False):
"""
Cache the result of a function call for the specified number of seconds,
using Django's caching mechanism.
- Assumes that the function never returns None (as the cache returns None to indicate a miss), and that the function's result only depends on its parameters.
- Note that the ordering of parameters is important. e.g. myFunction(x = 1, y = 2), myFunction(y = 2, x = 1), and myFunction(1,2) will each be cached separately.
+ Assumes that the function never returns None (as the cache returns None to indicate a miss),
+ and that the function's result only depends on its parameters.
+ Note that the ordering of parameters is important. e.g.
+ myFunction(x = 1, y = 2), myFunction(y = 2, x = 1), and myFunction(1,2)
+ will each be cached separately.
Usage:
Modified: geany/hosts.py
31 lines changed, 22 insertions(+), 9 deletions(-)
===================================================================
@@ -3,20 +3,20 @@
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
-#
+#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
-#
+#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-from django_hosts import patterns, host
+from django_hosts import host, patterns
from django_hosts.callbacks import cached_host_site
-#----------------------------------------------------------------------
+# ----------------------------------------------------------------------
def cached_host_site_extended(request, *args, **kwargs):
# call the original django-hosts callback to do the work
cached_host_site(request, *args, **kwargs)
@@ -26,14 +26,27 @@ def cached_host_site_extended(request, *args, **kwargs):
request.site_id = request.site.id
-host_patterns = patterns('',
+host_patterns = patterns(
+ '',
# nightlybuilds (nightly.geany.org and nightly.local.geany.org)
- host(r'^nightly(\.local|\.dev)?\.geany\.org(:[0-9]*)?$', 'nightlybuilds.urls', name='nightly.geany.org', callback=cached_host_site_extended),
- host(r'^geany\.nightlybuilds\.org(:[0-9]*)?$', 'nightlybuilds.urls', name='geany.nightlybuilds.org', callback=cached_host_site_extended),
+ host(
+ r'^nightly(\.local|\.dev)?\.geany\.org(:[0-9]*)?$', 'nightlybuilds.urls',
+ name='nightly.geany.org',
+ callback=cached_host_site_extended),
+ host(
+ r'^geany\.nightlybuilds\.org(:[0-9]*)?$', 'nightlybuilds.urls',
+ name='geany.nightlybuilds.org',
+ callback=cached_host_site_extended),
# pastebin (pastebin.geany.org and pastebin.local.geany.org)
- host(r'^pastebin(\.local|\.dev)?\.geany\.org(:[0-9]*)?$', 'pastebin.urls', name='pastebin.geany.org', callback=cached_host_site_extended),
+ host(
+ r'^pastebin(\.local|\.dev)?\.geany\.org(:[0-9]*)?$', 'pastebin.urls',
+ name='pastebin.geany.org',
+ callback=cached_host_site_extended),
# default
- host(r'^www\.geany\.org(:[0-9]*)?$', 'geany.urls', name='www.geany.org', callback=cached_host_site_extended),
+ host(
+ r'^www\.geany\.org(:[0-9]*)?$', 'geany.urls',
+ name='www.geany.org',
+ callback=cached_host_site_extended),
)
Modified: geany/management/commands/dump_database.py
3 lines changed, 1 insertions(+), 2 deletions(-)
===================================================================
@@ -15,11 +15,10 @@
from django.core.management import BaseCommand, call_command
-########################################################################
class Command(BaseCommand):
help = "Dump the database (excluding users, sessions and logs)"
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def handle(self, *args, **options):
call_command(
'dumpdata',
Modified: geany/settings.py
42 lines changed, 26 insertions(+), 16 deletions(-)
===================================================================
@@ -13,9 +13,12 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import absolute_import, unicode_literals
+
import os
+
from django.utils.translation import ugettext_lazy as _
+
######################
# MEZZANINE SETTINGS #
######################
@@ -133,6 +136,7 @@
ALLOWED_HOSTS = ('127.0.0.1',
'geany.org',
'www.geany.org')
+INTERNAL_IPS = ("127.0.0.1", "10.0.44.3", "37.120.182.205", "2a03:4000:f:40f:99::205")
# Local time zone for this installation. Choices can be found here:
@@ -407,8 +411,14 @@
)
ADMIN_MENU_ORDER = (
- (_("Content"), ("pages.Page", "blog.BlogPost", "news.NewsPost",
- "generic.ThreadedComment", "mezzanine_blocks.Block", "mezzanine_blocks.RichBlock", (_("Media Library"), "fb_browse"),)),
+ (_("Content"), (
+ "pages.Page",
+ "blog.BlogPost",
+ "news.NewsPost",
+ "generic.ThreadedComment",
+ "mezzanine_blocks.Block",
+ "mezzanine_blocks.RichBlock",
+ (_("Media Library"), "fb_browse"),)),
(_("Site"), (
"sites.Site",
"redirects.Redirect",
@@ -471,9 +481,9 @@
}
},
'handlers': {
- 'console':{
- 'level':'DEBUG',
- 'class':'logging.StreamHandler',
+ 'console': {
+ 'level': 'DEBUG',
+ 'class': 'logging.StreamHandler',
'formatter': 'verbose'
},
'mail_admins': {
@@ -484,22 +494,22 @@
},
'loggers': {
'': {
- 'handlers':['console', 'mail_admins'],
- 'level':'DEBUG',
+ 'handlers': ['console', 'mail_admins'],
+ 'level': 'DEBUG',
'propagate': False,
},
'root': {
- 'handlers':['console', 'mail_admins'],
- 'level':'DEBUG',
+ 'handlers': ['console', 'mail_admins'],
+ 'level': 'DEBUG',
'propagate': False,
},
'py.warnings': {
'propagate': True,
- 'level':'DEBUG',
+ 'level': 'DEBUG',
},
'django': {
'propagate': True,
- 'level':'DEBUG',
+ 'level': 'DEBUG',
},
'django.db': {
'level': 'INFO',
@@ -521,7 +531,7 @@
# IGNORE WARNINGS #
###################
SILENCED_SYSTEM_CHECKS = (
- 'fields.W162' # warning about longtext index in easy-audit not supported on MySQL
+ 'fields.W162' # warning about longtext index in easy-audit not supported on MySQL
)
@@ -536,15 +546,15 @@
# Instead of doing "from .local_settings import *", we use exec so that
# local_settings has full access to everything defined in this module.
-f = os.path.join(PROJECT_APP_PATH, 'local_settings.py')
-if os.path.exists(f):
+filename = os.path.join(PROJECT_APP_PATH, 'local_settings.py')
+if os.path.exists(filename):
import sys
import imp
module_name = '{}.local_settings'.format(PROJECT_APP)
module = imp.new_module(module_name)
- module.__file__ = f
+ module.__file__ = filename
sys.modules[module_name] = module
- exec(open(f, 'rb').read())
+ exec(open(filename, 'rb').read())
####################
Modified: geany/sitemaps.py
53 lines changed, 25 insertions(+), 28 deletions(-)
===================================================================
@@ -19,6 +19,7 @@
from mezzanine.conf import settings
from mezzanine.core.sitemaps import DisplayableSitemap
+
"""
Sitemap generation
GeanyMainSitemap is the main class which generates sitemap items
@@ -35,7 +36,6 @@
"""
-########################################################################
class GeanyMainSitemap(DisplayableSitemap):
"""
Sitemap class for Django's sitemaps framework that returns
@@ -44,59 +44,57 @@ class GeanyMainSitemap(DisplayableSitemap):
changefreq = 'monthly'
priority = 0.5
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def items(self):
items = super(GeanyMainSitemap, self).items()
additional_app_items = self._get_additional_app_items()
items.extend(additional_app_items)
return items
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def _get_additional_app_items(self):
return sitemap_registry.get_all_items()
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def lastmod(self, obj):
return getattr(obj, 'publish_date', None)
-########################################################################
class SitemapItem(object):
"""Simulate a model, mainly to provide get_absolute_url() for Sitemaps"""
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def __init__(self, name, absolute_url, publish_date=None, priority=0.5):
self._name = name
self._absolute_url = absolute_url
self._publish_date = publish_date
self._priority = priority
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def get_absolute_url(self):
return self._absolute_url
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
@property
def name(self):
return self._name
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
@property
def publish_date(self):
return self._publish_date
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
@property
def priority(self):
return self._priority
-########################################################################
class StaticSitemap(sitemaps.Sitemap):
"""Return the static sitemap items"""
priority = 0.5
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def __init__(self, domain, patterns):
self._domain = domain
self._patterns = patterns
@@ -105,82 +103,81 @@ def __init__(self, domain, patterns):
self._url_mapping = {}
self._get_site_and_host()
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def items(self):
return self.get_static_items() + self.get_dynamic_items()
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def get_static_items(self):
self._initialize()
return [SitemapItem(name, url) for name, url in self._url_mapping.items()]
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def _initialize(self):
for pattern in self._patterns:
if getattr(pattern, 'name', None) is not None:
url_resolved = self._resolve_url(pattern.name)
if url_resolved:
self._url_mapping[pattern.name] = url_resolved
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def _get_site_and_host(self):
self._site = Site.objects.get(domain=self._domain)
self._host = get_host(self._domain)
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def _resolve_url(self, url):
try:
return reverse(url, urlconf=self._host.urlconf)
except NoReverseMatch:
return None
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def get_dynamic_items(self):
return list()
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def changefreq(self, obj):
return 'monthly'
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def location(self, obj):
return self._url_mapping[obj.name]
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def get_urls(self, page=1, site=None, protocol=None):
# pass our site to the parent as we know better which site we are on
return super(StaticSitemap, self).get_urls(page, self._site, protocol)
-########################################################################
class SitemapRegistry(object):
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def __init__(self):
self._sitemap_generators = list()
self._static_items = None
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def add(self, generator_class, url_patterns, site_domain=None):
if site_domain is None:
site_domain = settings.SITE_DOMAIN_WWW
sitemap_generator_item = (generator_class, url_patterns, site_domain)
self._sitemap_generators.append(sitemap_generator_item)
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def _update_static_sitemap_items(self, sitemap_generator_class, url_patterns, site_domain):
generator = sitemap_generator_class(site_domain, url_patterns)
items = generator.get_static_items()
self._static_items.extend(items)
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def get_all_items(self):
if self._static_items is None:
self._static_items = self._get_static_items()
dynamic_items = self._get_dynamic_items()
return self._static_items + dynamic_items
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def _get_static_items(self):
static_items = list()
for sitemap_generator_class, url_patterns, site_domain in self._sitemap_generators:
@@ -189,7 +186,7 @@ def _get_static_items(self):
static_items.extend(items)
return static_items
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def _get_dynamic_items(self):
dynamic_items = list()
for sitemap_generator_class, url_patterns, site_domain in self._sitemap_generators:
Modified: geany/templatetags/geany_tags.py
29 lines changed, 15 insertions(+), 14 deletions(-)
===================================================================
@@ -12,38 +12,39 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import logging
+
from django import template
from django.conf import settings
from mezzanine.template import Library
-import logging
+
register = Library()
logger = logging.getLogger(__name__)
-########################################################################
class EvaluateNode(template.Node):
- """As found on http://stackoverflow.com/questions/1278042/in-django-is-there-an-easy-way-to-render-a-text-field-as-a-template-in-a-templ"""
+ """As found on http://stackoverflow.com/questions/1278042/in-django-is-there-an-easy-way-to-render-a-text-field-as-a-template-in-a-templ""" # noqa: E501 pylint: disable=line-too-long
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def __init__(self, variable, target_var_name):
self._variable = template.Variable(variable)
self._target_var_name = target_var_name
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def render(self, context):
try:
content = self._variable.resolve(context)
content_template = template.Template(content)
rendered_content = content_template.render(context)
context[self._target_var_name] = rendered_content
except (template.VariableDoesNotExist, template.TemplateSyntaxError) as e:
- return u'Error rendering: %s' % unicode(e)
+ return 'Error rendering: %s' % unicode(e)
return ''
-#----------------------------------------------------------------------
+# ----------------------------------------------------------------------
@register.tag(name='evaluate')
def do_evaluate(parser, token):
"""
@@ -52,32 +53,32 @@ def do_evaluate(parser, token):
try:
_, variable, _, target_var_name = token.split_contents()
except ValueError:
- raise template.TemplateSyntaxError(u'%r tag requires a single argument' %
- token.contents.split()[1])
+ raise template.TemplateSyntaxError(
+ '%r tag requires a single argument' % token.contents.split()[1])
return EvaluateNode(variable, target_var_name)
-#----------------------------------------------------------------------
+# ----------------------------------------------------------------------
@register.simple_tag
def get_irc_userlist():
user_list = list()
try:
with open(settings.IRC_USER_LIST_FILE) as file_h:
user_list = file_h.readlines()
except IOError as e:
- logger.error(u'An error occurred reading IRC user list: %s', unicode(e), exc_info=True)
+ logger.error('An error occurred reading IRC user list: %s', unicode(e), exc_info=True)
# remove newline characters
user_list = [username.strip() for username in user_list]
return sorted(user_list)
-#----------------------------------------------------------------------
+# ----------------------------------------------------------------------
@register.filter(name='add_css')
def add_css(field, css):
# read existing CSS classes
- css_classes = field.field.widget.attrs.get('class', u'')
+ css_classes = field.field.widget.attrs.get('class', '')
# add new ones
- css_classes = u'%s %s' % (css_classes, css)
+ css_classes = '%s %s' % (css_classes, css)
# render the widget
return field.as_widget(attrs={'class': css_classes})
Modified: geany/urls.py
4 lines changed, 2 insertions(+), 2 deletions(-)
===================================================================
@@ -26,6 +26,7 @@
from geany.sitemaps import GeanyMainSitemap
from nightlybuilds.views import NightlyBuildsView
+
sitemaps = {"sitemaps": {"all": GeanyMainSitemap}}
@@ -83,5 +84,4 @@
if settings.DEBUG:
urlpatterns += (
- url(r'^media/(?P<path>.*)$', static_serve, {'document_root': settings.MEDIA_ROOT, }),
- )
+ url(r'^media/(?P<path>.*)$', static_serve, {'document_root': settings.MEDIA_ROOT, }),)
Modified: geany/wsgi.py
6 lines changed, 4 insertions(+), 2 deletions(-)
===================================================================
@@ -12,7 +12,9 @@
from django.core.wsgi import get_wsgi_application
from mezzanine.utils.conf import real_project_name
-os.environ.setdefault("DJANGO_SETTINGS_MODULE",
- "%s.settings" % real_project_name("geany"))
+
+os.environ.setdefault(
+ "DJANGO_SETTINGS_MODULE",
+ "{}.settings".format(real_project_name("geany")))
application = get_wsgi_application()
Modified: latest_version/admin.py
10 lines changed, 5 insertions(+), 5 deletions(-)
===================================================================
@@ -3,30 +3,30 @@
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
-#
+#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
-#
+#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from django.contrib import admin
+
from latest_version.models import LatestVersion
-########################################################################
class LatestVersionAdmin(admin.ModelAdmin):
model = LatestVersion
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def has_add_permission(self, request):
"""A fake model should not be added"""
return False
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def has_delete_permission(self, request, obj=None):
"""A fake model should not be added"""
return False
Modified: latest_version/context_processors.py
8 lines changed, 4 insertions(+), 4 deletions(-)
===================================================================
@@ -3,20 +3,20 @@
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
-#
+#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
-#
+#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-from latest_version.models import LatestVersion
from geany.decorators import cache_function, CACHE_TIMEOUT_1HOUR
+from latest_version.models import LatestVersion
-#----------------------------------------------------------------------
+# ----------------------------------------------------------------------
@cache_function(CACHE_TIMEOUT_1HOUR, ignore_arguments=True)
def latest_version(request):
geany_latest_version = LatestVersion.objects.get(id=1)
Modified: latest_version/models.py
22 lines changed, 11 insertions(+), 11 deletions(-)
===================================================================
@@ -15,33 +15,33 @@
from django.db import models
-########################################################################
class LatestVersion(models.Model):
- version = models.CharField(max_length=50, verbose_name=u'Latest Geany version')
- github_link = models.CharField(max_length=255, verbose_name=u'Link to the Commits page on Github (everything after https://github.com/geany/geany/)')
+ version = models.CharField(max_length=50, verbose_name='Latest Geany version')
release_date = models.DateTimeField()
+ github_link = models.CharField(
+ max_length=255,
+ verbose_name='Link to the Commits page on Github (everything after '
+ 'https://github.com/geany/geany/)')
-
- ########################################################################
class Meta:
- verbose_name = u'Latest Version'
- verbose_name_plural = u'Latest Version'
+ verbose_name = 'Latest Version'
+ verbose_name_plural = 'Latest Version'
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def save(self):
"""Save but replace the existing row instead of adding a new one"""
self.id = 1
models.Model.save(self)
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def delete(self):
"""Never delete anything"""
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def __unicode__(self):
return str(self)
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def __str__(self):
return 'Geany {}'.format(self.version)
Modified: latest_version/urls.py
7 lines changed, 2 insertions(+), 5 deletions(-)
===================================================================
@@ -14,7 +14,8 @@
from django.conf.urls import url
from django.views.generic import TemplateView
-from geany.sitemaps import StaticSitemap, sitemap_registry
+
+from geany.sitemaps import sitemap_registry, StaticSitemap
urlpatterns = (
@@ -25,9 +26,5 @@
name='latest_version'),
)
-# Adds ``STATIC_URL`` to the context of error pages, so that error pages can use JS, CSS and images.
-handler404 = "mezzanine.core.views.page_not_found"
-handler500 = "mezzanine.core.views.server_error"
-
# register our urlpatterns to the global sitemap generator
sitemap_registry.add(StaticSitemap, urlpatterns)
Modified: news/admin.py
7 lines changed, 3 insertions(+), 4 deletions(-)
===================================================================
@@ -18,7 +18,6 @@
from news.models import NewsPost
-########################################################################
class NewsPostAdmin(admin.ModelAdmin):
list_display = ('title', 'user', 'status', 'publish_date')
list_editable = ("status",)
@@ -28,14 +27,14 @@ class NewsPostAdmin(admin.ModelAdmin):
actions = ['_toggle_many_published']
radio_fields = {"status": admin.HORIZONTAL}
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def save_model(self, request, obj, form, change):
if not obj.user_id:
# set logged in user as author
obj.user = request.user
obj.save()
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def _toggle_many_published(self, request, queryset):
# this is not really as efficient as it could be as the query is performed, but I don't know
# a way to get the primary keys in the queryset without executing it
@@ -45,7 +44,7 @@ def _toggle_many_published(self, request, queryset):
rows_updated += 1
self.message_user(request, "{} News posts were successfully changed.".format(rows_updated))
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def _toggle_newspost_published_status(self, newspost):
if newspost.status == CONTENT_STATUS_PUBLISHED:
newspost.status = CONTENT_STATUS_DRAFT
Modified: news/feeds.py
16 lines changed, 8 insertions(+), 8 deletions(-)
===================================================================
@@ -14,42 +14,42 @@
from django.contrib.syndication.views import Feed
from django.urls import reverse
+from mezzanine.conf import settings
from mezzanine.core.templatetags.mezzanine_tags import richtext_filters
from mezzanine.utils.html import absolute_urls
-from mezzanine.conf import settings
+
from news.models import NewsPost
-########################################################################
class LatestNewsPostsFeed(Feed):
title = "Geany project news"
description = "News feed for the Geany project"
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def link(self):
return reverse("news_list")
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def items(self):
return NewsPost.objects.recently_published(count=200)
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def item_title(self, item):
return item.title
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def item_description(self, item):
description = richtext_filters(item.content)
absolute_urls_name = "mezzanine.utils.html.absolute_urls"
if absolute_urls_name not in settings.RICHTEXT_FILTERS:
description = absolute_urls(description)
return description
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def item_pubdate(self, item):
return item.publish_date
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def item_author_name(self, item):
return item.user.get_full_name() or item.user.username
Modified: news/models.py
23 lines changed, 10 insertions(+), 13 deletions(-)
===================================================================
@@ -23,7 +23,6 @@
from mezzanine.utils.urls import slugify
-########################################################################
class PublishedManager(models.Manager):
"""
Provides filter for restricting items returned by status and
@@ -32,7 +31,7 @@ class PublishedManager(models.Manager):
# this is a clone of mezzanine.core.managers.PublishedManager but with the
# 'expiry_date' field removed
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def published(self, for_user=None):
"""
For non-staff users, return items with a published status and
@@ -45,16 +44,15 @@ def published(self, for_user=None):
models.Q(publish_date__lte=now()) | models.Q(publish_date__isnull=True),
models.Q(status=CONTENT_STATUS_PUBLISHED))
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def recently_published(self, count=5, for_user=None):
return self.published(for_user).order_by('-publish_date')[:count]
-########################################################################
class NewsPost(models.Model):
slug = models.CharField(_('Slug'), max_length=255, editable=False, db_index=True)
- title = models.CharField(_(u'Title'), max_length=255, blank=True)
+ title = models.CharField(_('Title'), max_length=255, blank=True)
content = RichTextField(_('Content'))
user = models.ForeignKey(
get_user_model_name(),
@@ -68,35 +66,34 @@ class NewsPost(models.Model):
db_index=True,
help_text=_('With Draft chosen, will only be shown for admin users on the site.'))
entry_date = models.DateTimeField(
- _(u'Published'),
+ _('Published'),
editable=False,
auto_now_add=True,
db_index=True)
publish_date = models.DateTimeField(
- _(u'Published on'),
+ _('Published on'),
blank=True,
db_index=True,
default=timezone.now)
# add a 'published' method to the Manager to filter by published status
objects = PublishedManager()
- ########################################################################
class Meta:
ordering = ('-publish_date',)
- verbose_name = _(u'News')
- verbose_name_plural = _(u'News')
+ verbose_name = _('News')
+ verbose_name_plural = _('News')
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super(NewsPost, self).save(*args, **kwargs)
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def get_absolute_url(self):
return reverse('news_detail', kwargs={'newspost_slug': self.slug})
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def __unicode__(self):
return self.title
Modified: news/sitemaps.py
3 lines changed, 1 insertions(+), 2 deletions(-)
===================================================================
@@ -16,10 +16,9 @@
from news.models import NewsPost
-########################################################################
class NewsPostSitemap(StaticSitemap):
"""Return the static sitemap items + the last five most recent News posts"""
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def get_dynamic_items(self):
return list(NewsPost.objects.recently_published(count=30))
Modified: news/templatetags/news_tags.py
4 lines changed, 3 insertions(+), 1 deletions(-)
===================================================================
@@ -13,12 +13,14 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from django import template
+
from news.models import NewsPost
+
register = template.Library()
-#----------------------------------------------------------------------
+# ----------------------------------------------------------------------
@register.inclusion_tag("news/list_embedded.html", takes_context=True)
def get_recent_news(context):
user = context.request.user
Modified: news/urls.py
3 lines changed, 2 insertions(+), 1 deletions(-)
===================================================================
@@ -13,10 +13,11 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from django.conf.urls import url
+
from geany.sitemaps import sitemap_registry
from news.feeds import LatestNewsPostsFeed
from news.sitemaps import NewsPostSitemap
-from news.views import NewsListView, NewsDetailView
+from news.views import NewsDetailView, NewsListView
urlpatterns = (
Modified: news/views.py
17 lines changed, 7 insertions(+), 10 deletions(-)
===================================================================
@@ -13,19 +13,19 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from django.http import JsonResponse
-from django.shortcuts import render, get_object_or_404
+from django.shortcuts import get_object_or_404, render
from django.template.defaultfilters import date, safe
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt
from django.views.generic import DetailView, ListView, View
from mezzanine.core.templatetags.mezzanine_tags import richtext_filters
+
from news.models import NewsPost
-########################################################################
class NewsPostPublishedMixin(object):
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def get_queryset(self):
""" filter non-published news posts except for staff users """
user = self.request.user
@@ -34,41 +34,38 @@ def get_queryset(self):
order_by('-publish_date')
-########################################################################
class NewsListView(NewsPostPublishedMixin, ListView):
model = NewsPost
template_name = 'news/list.html'
-########################################################################
class NewsDetailView2(NewsPostPublishedMixin, DetailView):
model = NewsPost
template_name = 'news/detail.html'
-########################################################################
class NewsDetailView(NewsPostPublishedMixin, View):
template_name = 'news/detail.html'
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
@method_decorator(csrf_exempt)
def dispatch(self, *args, **kwargs):
return super(NewsDetailView, self).dispatch(*args, **kwargs)
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def get(self, request, newspost_slug):
newspost = get_object_or_404(NewsPost, slug=newspost_slug)
return render(request, self.template_name, {'newspost': newspost})
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def post(self, request, *args, **kwargs):
newspost_slug = request.POST.get('newspost_slug')
try:
newspost = NewsPost.objects.get(slug=newspost_slug)
except NewsPost.DoesNotExist:
- error_message = u'News post item for "{}" could not be found'.format(newspost_slug)
+ error_message = 'News post item for "{}" could not be found'.format(newspost_slug)
result = dict(error=error_message)
else:
# adapt to dict
Modified: nightlybuilds/database_routers.py
9 lines changed, 4 insertions(+), 5 deletions(-)
===================================================================
@@ -13,13 +13,12 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-########################################################################
class NightlyBuildsRouter(object):
"""
A router to control all database operations on models in the
nightlybuilds application.
"""
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def db_for_read(self, model, **hints):
"""
Attempts to read auth models go to nightlybuilds.
@@ -28,7 +27,7 @@ def db_for_read(self, model, **hints):
return 'nightlybuilds'
return None
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def db_for_write(self, model, **hints):
"""
Attempts to write auth models go to nightlybuilds.
@@ -37,7 +36,7 @@ def db_for_write(self, model, **hints):
return 'nightlybuilds'
return None
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def allow_relation(self, obj1, obj2, **hints):
"""
Allow relations if a model in the auth app is involved.
@@ -47,6 +46,6 @@ def allow_relation(self, obj1, obj2, **hints):
return True
return None
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def allow_migrate(self, db, app_label, model_name=None, **hints):
return app_label != 'nightlybuilds'
Modified: nightlybuilds/models.py
18 lines changed, 7 insertions(+), 11 deletions(-)
===================================================================
@@ -15,7 +15,6 @@
from django.db import models
-########################################################################
class NightlyBuildTarget(models.Model):
nightly_build_target_id = models.PositiveIntegerField(primary_key=True)
@@ -31,17 +30,15 @@ class NightlyBuildTarget(models.Model):
blank=True,
on_delete=models.PROTECT)
- ########################################################################
class Meta:
ordering = ('name', 'arch')
db_table = 'nightly_build_target'
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def __unicode__(self):
return '%s %s' % (self.name, self.arch)
-########################################################################
class NightlyBuild(models.Model):
nightly_build_id = models.PositiveIntegerField(primary_key=True)
@@ -57,22 +54,21 @@ class NightlyBuild(models.Model):
build_host = models.CharField(max_length=255)
build_date = models.DateTimeField(max_length=255)
- ########################################################################
class Meta:
ordering = ('-build_date',)
db_table = 'nightly_build'
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def get_status(self):
return not self.status
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def get_status_text(self):
if self.get_status():
- return u'Built successfully'
- else:
- return 'Build failed, see the logs for details'
+ return 'Built successfully'
- #----------------------------------------------------------------------
+ return 'Build failed, see the logs for details'
+
+ # ----------------------------------------------------------------------
def __unicode__(self):
return '%s %s' % (self.build_date, self.nightly_build_target)
Modified: nightlybuilds/templatetags/nightlybuilds_tags.py
19 lines changed, 10 insertions(+), 9 deletions(-)
===================================================================
@@ -12,20 +12,21 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import os
+
from django import template
from django.conf import settings
from django.utils.html import format_html
-import os
register = template.Library()
base_dir = settings.NIGHTLYBUILDS_BASE_DIR
-#----------------------------------------------------------------------
+# ----------------------------------------------------------------------
@register.simple_tag
def get_build_log(nightly_build, log_type):
- if log_type == u'Stdout':
+ if log_type == 'Stdout':
log = nightly_build.log_stdout
else:
log = nightly_build.log_stderr
@@ -39,20 +40,20 @@ def get_build_log(nightly_build, log_type):
else:
if size > 0:
return format_html(
- u'<a href="/{}/{}">{}</stdout>',
+ '<a href="/{}/{}">{}</stdout>',
nightly_build.nightly_build_target.folder,
log,
log_type)
- return u''
+ return ''
-#----------------------------------------------------------------------
+# ----------------------------------------------------------------------
@register.simple_tag
def get_details(nightly_build):
header_txt = os.path.join(base_dir, nightly_build.nightly_build_target.folder, 'HEADER.txt')
if os.path.exists(header_txt):
return format_html(
- u'<a href="/{}/">Details</a>',
+ '<a href="/{}/">Details</a>',
nightly_build.nightly_build_target.folder)
- else:
- return u''
+
+ return ''
Modified: nightlybuilds/urls.py
15 lines changed, 2 insertions(+), 13 deletions(-)
===================================================================
@@ -12,8 +12,8 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-from django.conf import settings
-from django.conf.urls import include, url
+from django.conf.urls import url
+
from geany.sitemaps import StaticSitemap
from nightlybuilds.views import NightlyBuildsView
@@ -25,20 +25,9 @@
url(r'^$', NightlyBuildsView.as_view(), name='home'),
]
-# Django-Debug-Toolbar support
-if settings.DEBUG:
- import debug_toolbar
- urlpatterns += (
- url(r'^__debug__/', include(debug_toolbar.urls)),
- )
-
# Sitemap framework
sitemaps = {"sitemaps": {"all": StaticSitemap('nightly.geany.org', urlpatterns)}}
urlpatterns += (
# use our custom sitemap implementation
url(r"^sitemap\.xml$", 'django.contrib.sitemaps.views.sitemap', sitemaps),
)
-
-# Adds ``STATIC_URL`` to the context of error pages, so that error pages can use JS, CSS and images.
-handler404 = "mezzanine.core.views.page_not_found"
-handler500 = "mezzanine.core.views.server_error"
Modified: nightlybuilds/views.py
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -14,10 +14,10 @@
from django.db.models import F
from django.views.generic import ListView
+
from nightlybuilds.models import NightlyBuild
-########################################################################
class NightlyBuildsView(ListView):
template_name = "nightlybuilds.html"
Modified: pastebin/admin.py
8 lines changed, 4 insertions(+), 4 deletions(-)
===================================================================
@@ -3,25 +3,25 @@
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
-#
+#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
-#
+#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
from django.contrib import admin
+
from pastebin.models import Snippet, Spamword
-########################################################################
class SnippetAdmin(admin.ModelAdmin):
list_display = ('published', 'expires', 'author', 'title')
date_hierarchy = 'published'
list_filter = ('published',)
+
admin.site.register(Snippet, SnippetAdmin)
admin.site.register(Spamword)
Modified: pastebin/api/create.py
24 lines changed, 13 insertions(+), 11 deletions(-)
===================================================================
@@ -13,9 +13,11 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from datetime import timedelta
+
from django.utils.timezone import now
+
from pastebin.forms import SnippetForm
-from pastebin.highlight import LEXER_LIST_ALL, LEXER_DEFAULT
+from pastebin.highlight import LEXER_DEFAULT, LEXER_LIST_ALL
from pastebin.models import Snippet
@@ -66,38 +68,37 @@
}
-########################################################################
class SnippetValidationError(Exception):
pass
-########################################################################
class CreateSnippetApiController(object):
valid_fields = ('title', 'content', 'expires', 'author', 'lexer')
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def __init__(self, request):
self._request = request
self._data = request.POST.copy()
self._snippet = None
self._snippet_form = None
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def create(self):
self._validate_passed_fields()
self._validate_against_snippet_form()
self._create_snippet()
return self._snippet
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def _validate_passed_fields(self):
provided_fields = set(self._data.keys())
additional_fields = provided_fields.difference(self.valid_fields)
if additional_fields:
- raise SnippetValidationError(u'Invalid fields provided (%s)' % ','.join(additional_fields))
+ raise SnippetValidationError(
+ 'Invalid fields provided (%s)' % ','.join(additional_fields))
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def _validate_against_snippet_form(self):
self._preprocess_data()
@@ -107,11 +108,12 @@ def _validate_against_snippet_form(self):
snippet_form.fields['lexer'].choices = LEXER_LIST_ALL
# validate
if not snippet_form.is_valid():
- errors = u'\n'.join([u'%s: %s' % (k, v.as_text()) for k, v in snippet_form.errors.items()])
+ errors = '\n'.join(
+ ['%s: %s' % (k, v.as_text()) for k, v in snippet_form.errors.items()])
raise SnippetValidationError(errors)
self._snippet_form = snippet_form
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def _preprocess_data(self):
# compatibility with SnippetForm
self._data['expire_options'] = self._data.get('expires', 3600)
@@ -128,7 +130,7 @@ def _preprocess_data(self):
# lexers and simply override them with 'text'
self._data['lexer'] = LEXER_DEFAULT
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def _create_snippet(self):
cleaned_data = self._snippet_form.cleaned_data
expire_options = int(cleaned_data.get('expire_options', 3600))
Modified: pastebin/forms.py
31 lines changed, 16 insertions(+), 15 deletions(-)
===================================================================
@@ -13,51 +13,52 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from datetime import timedelta
+
from django import forms
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
-from pastebin.highlight import LEXER_LIST, LEXER_DEFAULT
+
+from pastebin.highlight import LEXER_DEFAULT, LEXER_LIST
from pastebin.models import Snippet, Spamword
-#===============================================================================
+# ===============================================================================
# Snippet Form and Handling
-#===============================================================================
+# ===============================================================================
EXPIRE_CHOICES = (
- (3600, _(u'In one hour')),
- (3600 * 24 * 7, _(u'In one week')),
- (3600 * 24 * 30, _(u'In one month')),
- (3600 * 24 * 30 * 12 * 100, _(u'Save forever')), # 100 years, I call it forever ;)
+ (3600, _('In one hour')),
+ (3600 * 24 * 7, _('In one week')),
+ (3600 * 24 * 30, _('In one month')),
+ (3600 * 24 * 30 * 12 * 100, _('Save forever')), # 100 years, I call it forever ;)
)
EXPIRE_DEFAULT = 3600 * 24 * 30
-########################################################################
class SnippetForm(forms.ModelForm):
lexer = forms.ChoiceField(
choices=LEXER_LIST,
initial=LEXER_DEFAULT,
- label=_(u'Lexer'),
+ label=_('Lexer'),
)
expire_options = forms.ChoiceField(
choices=EXPIRE_CHOICES,
initial=EXPIRE_DEFAULT,
- label=_(u'Expires'),
+ label=_('Expires'),
widget=forms.RadioSelect,
)
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def __init__(self, request, *args, **kwargs):
forms.ModelForm.__init__(self, *args, **kwargs)
self.request = request
# set author
self.fields['author'].initial = self.request.session.get('author', '')
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def clean_content(self):
content = self.cleaned_data.get('content')
if content:
@@ -66,9 +67,10 @@ def clean_content(self):
raise forms.ValidationError('This snippet was identified as SPAM.')
return content
- #----------------------------------------------------------------------
- def save(self, parent=None, *args, **kwargs):
+ # ----------------------------------------------------------------------
+ def save(self, *args, **kwargs):
# Set parent snippet
+ parent = kwargs.pop('parent', None)
if parent:
self.instance.parent = parent
@@ -89,7 +91,6 @@ def save(self, parent=None, *args, **kwargs):
return self.request, self.instance
- ########################################################################
class Meta:
model = Snippet
fields = (
Modified: pastebin/highlight.py
21 lines changed, 8 insertions(+), 13 deletions(-)
===================================================================
@@ -12,14 +12,10 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
from django.utils.html import escape
-from pygments.formatters import HtmlFormatter
from pygments import highlight
-from pygments.lexers import (
- PythonLexer,
- get_all_lexers,
- get_lexer_by_name)
+from pygments.formatters import HtmlFormatter
+from pygments.lexers import get_all_lexers, get_lexer_by_name, PythonLexer
LEXER_LIST_ALL = sorted([(i[1][0], i[0]) for i in get_all_lexers()])
@@ -52,30 +48,29 @@
LEXER_DEFAULT = 'text'
-########################################################################
class NakedHtmlFormatter(HtmlFormatter):
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def wrap(self, source, outfile):
return self._wrap_code(source)
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def _wrap_code(self, source):
for j, t in source:
yield j, t
-#----------------------------------------------------------------------
+# ----------------------------------------------------------------------
def pygmentize(code_string, lexer_name=LEXER_DEFAULT):
try:
if lexer_name:
lexer = get_lexer_by_name(lexer_name)
else:
- raise Exception(u'Unknown lexer')
- except:
+ raise Exception('Unknown lexer')
+ except Exception:
lexer = PythonLexer()
try:
return highlight(code_string, lexer, NakedHtmlFormatter())
- except:
+ except Exception:
return escape(code_string)
Modified: pastebin/management/commands/cleanup_snippets.py
30 lines changed, 17 insertions(+), 13 deletions(-)
===================================================================
@@ -3,38 +3,42 @@
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
-#
+#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
-#
+#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-from django.core.management.base import LabelCommand
from optparse import make_option
-from pastebin.models import Snippet
import datetime
import sys
+from django.core.management.base import LabelCommand
+
+from pastebin.models import Snippet
+
-########################################################################
class Command(LabelCommand):
option_list = LabelCommand.option_list + (
- make_option('--dry-run', '-d', action='store_true', dest='dry_run',
+ make_option(
+ '--dry-run', '-d',
+ action='store_true',
+ dest='dry_run',
help='Don\'t do anything.'),
)
- help = "Purges snippets that are expired"
+ help = 'Purges snippets that are expired'
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def handle(self, *args, **options):
deleteable_snippets = Snippet.objects.filter(expires__lte=datetime.datetime.now())
- sys.stdout.write(u"%s snippets gets deleted:\n" % deleteable_snippets.count())
- for d in deleteable_snippets:
- sys.stdout.write(u"- %s (%s)\n" % (d.secret_id, d.expires))
+ sys.stdout.write('{} snippets gets deleted:\n'.format(deleteable_snippets.count()))
+ for deleteable_snippet in deleteable_snippets:
+ sys.stdout.write(
+ u'- {} ({})\n'.format(deleteable_snippet.secret_id, deleteable_snippet.expires))
if options.get('dry_run'):
- sys.stdout.write(u'Dry run - Doing nothing! *crossingfingers*\n')
+ sys.stdout.write('Dry run - Doing nothing! *crossingfingers*\n')
else:
deleteable_snippets.delete()
Modified: pastebin/management/commands/generate_snippets_css.py
3 lines changed, 1 insertions(+), 2 deletions(-)
===================================================================
@@ -16,12 +16,11 @@
from pygments.formatters import HtmlFormatter
-########################################################################
class Command(BaseCommand):
help = "Regenerate CSS for snippet sxntax highlighting py Pygments"
requires_system_checks = False
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def handle(self, *args, **options):
with open('pastebin/static/css/pygments.css', 'w') as css_file:
# You can change style and the html class here:
Modified: pastebin/models.py
57 lines changed, 28 insertions(+), 29 deletions(-)
===================================================================
@@ -13,51 +13,51 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from datetime import timedelta
-from django.urls import reverse
+import random
+import re
+import time
+
from django.db import models
+from django.urls import reverse
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
+
from pastebin.highlight import LEXER_DEFAULT
-import random
-import re
-import time
t = 'abcdefghijkmnopqrstuvwwxyzABCDEFGHIJKLOMNOPQRSTUVWXYZ1234567890'
-#----------------------------------------------------------------------
+# ----------------------------------------------------------------------
def generate_secret_id(length=5):
- return ''.join([random.choice(t) for i in range(length)])
+ return ''.join([random.choice(t) for i in range(length)]) # pylint: disable=unused-variable
-########################################################################
class Snippet(models.Model):
- secret_id = models.CharField(_(u'Secret ID'), max_length=255, blank=True)
- title = models.CharField(_(u'Title'), max_length=120, blank=True)
- author = models.CharField(_(u'Author'), max_length=30, blank=True)
- content = models.TextField(_(u'Content'), )
- content_highlighted = models.TextField(_(u'Highlighted Content'), blank=True)
- lexer = models.CharField(_(u'Lexer'), max_length=30, default=LEXER_DEFAULT)
- published = models.DateTimeField(_(u'Published'), blank=True, db_index=True)
- expires = models.DateTimeField(_(u'Expires'), blank=True, db_index=True)
+ secret_id = models.CharField(_('Secret ID'), max_length=255, blank=True)
+ title = models.CharField(_('Title'), max_length=120, blank=True)
+ author = models.CharField(_('Author'), max_length=30, blank=True)
+ content = models.TextField(_('Content'), )
+ content_highlighted = models.TextField(_('Highlighted Content'), blank=True)
+ lexer = models.CharField(_('Lexer'), max_length=30, default=LEXER_DEFAULT)
+ published = models.DateTimeField(_('Published'), blank=True, db_index=True)
+ expires = models.DateTimeField(_('Expires'), blank=True, db_index=True)
parent = models.ForeignKey(
'self',
null=True,
blank=True,
related_name='children',
on_delete=models.PROTECT)
- ########################################################################
class Meta:
ordering = ('-published',)
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def age(self):
age = time.mktime(self.published.timetuple())
return self._readable_delta(age)
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def _readable_delta(self, from_seconds, until_seconds=None):
'''Returns a nice readable delta.
@@ -78,7 +78,7 @@ def _readable_delta(self, from_seconds, until_seconds=None):
delta_minutes = delta.seconds // 60
delta_hours = delta_minutes // 60
- ## show a fuzzy but useful approximation of the time delta
+ # show a fuzzy but useful approximation of the time delta
if delta.days:
return '%d days ago' % (delta.days)
elif delta_hours:
@@ -88,15 +88,15 @@ def _readable_delta(self, from_seconds, until_seconds=None):
else:
return '%d seconds ago' % (delta.seconds)
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def get_linecount(self):
return len(self.content.splitlines())
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def content_splitted(self):
return self.content_highlighted.splitlines()
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def save(self, *args, **kwargs):
if not self.pk and not self.secret_id:
self.secret_id = generate_secret_id()
@@ -106,29 +106,28 @@ def save(self, *args, **kwargs):
self.content_highlighted = self.content
models.Model.save(self, *args, **kwargs)
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def get_absolute_url(self):
return reverse('snippet_details', kwargs={'snippet_id': self.secret_id})
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def __unicode__(self):
return '%s' % self.secret_id
-########################################################################
class SpamwordManager(models.Manager):
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def get_regex(self):
- return re.compile(r'|'.join((i[1] for i in self.values_list())),
+ return re.compile(
+ r'|'.join((i[1] for i in self.values_list())),
re.MULTILINE)
-########################################################################
class Spamword(models.Model):
word = models.CharField(max_length=100)
objects = SpamwordManager()
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def __unicode__(self):
return self.word
Modified: pastebin/templatetags/pastebin_tags.py
18 lines changed, 10 insertions(+), 8 deletions(-)
===================================================================
@@ -15,33 +15,35 @@
from django.template import Library
from django.template.defaultfilters import timeuntil
from django.utils.timezone import now
+
from pastebin.highlight import pygmentize
+
NINETY_YEARS_IN_DAYS = 32850 # 90 * 365
-register = Library()
+register = Library() # pylint: disable=invalid-name
-#----------------------------------------------------------------------
+# ----------------------------------------------------------------------
@register.filter
def in_list(value, arg):
return value in arg
-#----------------------------------------------------------------------
+# ----------------------------------------------------------------------
@register.filter
def timeuntil_or_forever(snippet_expire):
ttl = snippet_expire - now()
if ttl.days > NINETY_YEARS_IN_DAYS:
# snippet TTL 'forever' is defined as 100 years, so if remaining TTL is more than
# (90 * 365) days, we most probably got a snippet with TTL 'forever'
- return u'forever'
- else:
- return timeuntil(snippet_expire)
+ return 'forever'
+
+ return timeuntil(snippet_expire)
-#----------------------------------------------------------------------
+# ----------------------------------------------------------------------
@register.filter
def highlight(snippet, line_count=None):
h = pygmentize(snippet.content, snippet.lexer)
@@ -52,5 +54,5 @@ def highlight(snippet, line_count=None):
if line_count:
lines = lines[:line_count]
- lines.append(u'...')
+ lines.append('...')
return lines
Modified: pastebin/urls.py
6 lines changed, 3 insertions(+), 3 deletions(-)
===================================================================
@@ -12,7 +12,6 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-from django.conf import settings
from django.conf.urls import url
from django.views.decorators.cache import never_cache
from django.views.generic.base import TemplateView
@@ -24,10 +23,11 @@
SnippetDeleteView,
SnippetDetailRawView,
SnippetDetailView,
- SnippetNewView)
+ SnippetNewView,
+)
-urlpatterns = (
+urlpatterns = ( # pylint: disable=invalid-name
url(r'^help/$', TemplateView.as_view(template_name='pastebin/help.html'), name='snippet_help'),
url(r'^help/api/$', TemplateView.as_view(template_name='pastebin/api.html'), name='snippet_help_api'),
Modified: pastebin/views.py
60 lines changed, 27 insertions(+), 33 deletions(-)
===================================================================
@@ -17,7 +17,6 @@
from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist
from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
-from django.template.context import RequestContext
from django.template.response import TemplateResponse
from django.urls import reverse
from django.utils import timezone
@@ -32,7 +31,7 @@
from pastebin.models import Snippet
-#----------------------------------------------------------------------
+# ----------------------------------------------------------------------
def _get_snippet_list(no_content=False):
try:
max_snippets = getattr(settings, 'MAX_SNIPPETS_PER_USER', 10)
@@ -48,27 +47,26 @@ def _get_snippet_list(no_content=False):
return snippet_list_
-########################################################################
class SnippetNewView(View):
template_name = 'pastebin/snippet_new.html'
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
@method_decorator(check_honeypot)
def dispatch(self, *args, **kwargs):
return super(SnippetNewView, self).dispatch(*args, **kwargs)
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def get(self, request):
snippet_form = SnippetForm(request=request)
return self._render_response(request, snippet_form)
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def _render_response(self, request, snippet_form):
snippet_list = _get_snippet_list(no_content=True)
template_context = dict(snippet_form=snippet_form, snippet_list=snippet_list)
return render(request, self.template_name, template_context)
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def post(self, request):
snippet_form = SnippetForm(data=request.POST, request=request)
if snippet_form.is_valid():
@@ -78,21 +76,19 @@ def post(self, request):
return self._render_response(request, snippet_form)
-########################################################################
class SnippetNotFoundError(Exception):
pass
-########################################################################
class SnippetDetailView(View):
template_name = 'pastebin/snippet_details.html'
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
@method_decorator(check_honeypot)
def dispatch(self, *args, **kwargs):
return super(SnippetDetailView, self).dispatch(*args, **kwargs)
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def get(self, request, snippet_id):
# housekeeping
self._clean_expired_snippets()
@@ -117,40 +113,40 @@ def get(self, request, snippet_id):
return render(request, self.template_name, template_context)
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def _clean_expired_snippets(self):
deleteable_snippets = Snippet.objects.filter(expires__lte=timezone.now())
if deleteable_snippets:
deleteable_snippets.delete()
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def _fetch_snippet(self, snippet_id):
try:
snippet = Snippet.objects.get(secret_id=snippet_id)
except MultipleObjectsReturned:
- raise SnippetNotFoundError(_(u'Multiple snippets exist for this slug. This should never happen.'))
+ raise SnippetNotFoundError(
+ _('Multiple snippets exist for this slug. This should never happen.'))
except ObjectDoesNotExist:
- raise SnippetNotFoundError(_(u'This snippet does not exist anymore. Probably its lifetime is expired.'))
+ raise SnippetNotFoundError(
+ _('This snippet does not exist anymore. Probably its lifetime is expired.'))
else:
return snippet
-########################################################################
class SnippetDetailRawView(SnippetDetailView):
template_name = 'pastebin/snippet_details_raw.html'
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def get(self, request, snippet_id):
response = super(SnippetDetailRawView, self).get(request, snippet_id)
# set content type
response['Content-Type'] = 'text/plain;charset=UTF-8'
return response
-########################################################################
class SnippetDeleteView(View):
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def get(self, request, snippet_id):
snippet = get_object_or_404(Snippet, secret_id=snippet_id)
try:
@@ -160,25 +156,24 @@ def get(self, request, snippet_id):
return TemplateResponse(
request,
'errors/403.html',
- context=dict(message=_(u'You have no recent snippet list, cookie error?')),
+ context=dict(message=_('You have no recent snippet list, cookie error?')),
status=403)
- if not snippet.pk in snippet_list_:
+ if snippet.pk not in snippet_list_:
# 403 response with custom message
return TemplateResponse(
request,
'errors/403.html',
- context=dict(message=_(u'That is not your snippet!')),
+ context=dict(message=_('That is not your snippet!')),
status=403)
snippet.delete()
return HttpResponseRedirect(reverse('snippet_new'))
-########################################################################
class LatestSnippetsView(TemplateView):
template_name = 'pastebin/snippet_list.html'
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def get_context_data(self, **kwargs):
snippet_list_ = _get_snippet_list()
@@ -188,30 +183,29 @@ def get_context_data(self, **kwargs):
return context
-########################################################################
class SnippetAPIView(View):
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
@method_decorator(csrf_exempt)
def dispatch(self, *args, **kwargs):
return super(SnippetAPIView, self).dispatch(*args, **kwargs)
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def post(self, request):
try:
controller = CreateSnippetApiController(request)
snippet = controller.create()
except SnippetValidationError as e:
- return HttpResponseBadRequest(unicode(e), content_type=u'text/plain')
+ return HttpResponseBadRequest(unicode(e), content_type='text/plain')
site = self._get_site(request)
absolute_url = snippet.get_absolute_url()
- result = u'https://%s%s/' % (site.domain, absolute_url)
- return HttpResponse(result, content_type=u'text/plain')
+ result = 'https://%s%s/' % (site.domain, absolute_url)
+ return HttpResponse(result, content_type='text/plain')
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def _get_site(self, request):
if hasattr(request, 'site'):
return request.site
- else:
- return Site.objects.get_current()
+
+ return Site.objects.get_current()
Modified: static_docs/generate_i18n_statistics.py
7 lines changed, 6 insertions(+), 1 deletions(-)
===================================================================
@@ -184,7 +184,12 @@ def _update_message_catalog(self):
destination_filename = join(self._destination_path, self._message_catalog.filename)
pot_file = self._factor_pot_filename()
- update_command = ['msgmerge', source_filename, pot_file, '--output-file', destination_filename]
+ update_command = [
+ 'msgmerge',
+ source_filename,
+ pot_file,
+ '--output-file',
+ destination_filename]
self._execute_command(update_command)
# ----------------------------------------------------------------------
Modified: static_docs/github_client.py
11 lines changed, 6 insertions(+), 5 deletions(-)
===================================================================
@@ -15,6 +15,7 @@
# try to get any json implementation
from base64 import standard_b64decode
import logging
+
import requests
@@ -26,11 +27,10 @@
logger = logging.getLogger(__name__)
-########################################################################
class GitHubApiClient(object):
""""""
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def get_file_contents(self, filename):
url_parameters = dict(user=GITHUB_USER,
repository=GITHUB_REPOSITORY,
@@ -44,16 +44,17 @@ def get_file_contents(self, filename):
# parse response
return self._parse_fetch_file_response(response_json)
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def _log_rate_limit(self, response):
rate_limit_remaining = response.headers['X-RateLimit-Remaining']
rate_limit = response.headers['X-RateLimit-Limit']
logger.info('Github rate limits: %s/%s', rate_limit_remaining, rate_limit)
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def _parse_fetch_file_response(self, response_json):
+ content = response_json['content']
if response_json['encoding'] == 'base64':
# standard_b64decode returns a byte string but we want a unicode string
- content_utf8 = standard_b64decode(response_json['content'])
+ content_utf8 = standard_b64decode(content)
return content_utf8.decode('utf-8')
return content
Modified: static_docs/management/commands/generate_i18n_statistics.py
1 lines changed, 0 insertions(+), 1 deletions(-)
===================================================================
@@ -18,7 +18,6 @@
from static_docs.generate_i18n_statistics import TranslationStatisticsGenerator
-########################################################################
class Command(BaseCommand):
help = "Generate a JSON file with I18N statistics after updating PO files"
Modified: static_docs/urls.py
5 lines changed, 1 insertions(+), 4 deletions(-)
===================================================================
@@ -13,6 +13,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from django.conf.urls import url
+
from static_docs.views import I18NStatisticsView, ReleaseNotesView, ToDoView
@@ -30,7 +31,3 @@
I18NStatisticsView.as_view(),
name='translation_statistics'),
)
-
-# Adds ``STATIC_URL`` to the context of error pages, so that error pages can use JS, CSS and images.
-handler404 = "mezzanine.core.views.page_not_found"
-handler500 = "mezzanine.core.views.server_error"
Modified: static_docs/views.py
45 lines changed, 20 insertions(+), 25 deletions(-)
===================================================================
@@ -22,55 +22,52 @@
from django.http import Http404
from django.views.generic.base import TemplateView
-from static_docs.github_client import GitHubApiClient
from geany.decorators import cache_function, CACHE_TIMEOUT_1HOUR, CACHE_TIMEOUT_24HOURS
+from static_docs.github_client import GitHubApiClient
RELEASE_REGEXP = re.compile(r'^Geany (?P<version>[0-9\.]+) \((?P<date>.*)\)$')
-DATE_PATTERNS_TO_BE_IGNORED = (u'TBD', u'TBA', u'unreleased')
+DATE_PATTERNS_TO_BE_IGNORED = ('TBD', 'TBA', 'unreleased')
logger = logging.getLogger(__name__)
-########################################################################
class ReleaseDto(object):
"""Simple data holder"""
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def __init__(self):
self.version = None
self.release_date = None
self.release_notes = None
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def __repr__(self):
- return u'Geany %s (%s)' % (self.version, self.release_date)
+ return 'Geany %s (%s)' % (self.version, self.release_date)
-########################################################################
class StaticDocsView(TemplateView):
""""""
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def __init__(self, *args, **kwargs):
super(StaticDocsView, self).__init__(*args, **kwargs)
self._file_contents = None
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def _fetch_file_via_github_api(self, filename):
client = GitHubApiClient()
self._file_contents = client.get_file_contents(filename)
-########################################################################
class ReleaseNotesView(StaticDocsView):
"""
Grab the NEWS file from GIT master via Github API, parse it and send it back to the template
"""
- template_name = "pages/documentation/releasenotes.html"
+ template_name = 'pages/documentation/releasenotes.html'
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def get_context_data(self, version=None, **kwargs):
releases = self._get_release_notes()
release = None
@@ -93,27 +90,27 @@ def get_context_data(self, version=None, **kwargs):
context['releases'] = releases
return context
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
@cache_function(CACHE_TIMEOUT_24HOURS)
def _get_release_notes(self):
self._fetch_file_via_github_api('NEWS')
return self._parse_news_file()
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def _parse_news_file(self):
releases = list()
current_release = None
current_release_notes = None
for line in self._file_contents.splitlines():
- if line.startswith(u'Geany'):
+ if line.startswith('Geany'):
version, date = self._parse_release_line(line)
if not version or date in DATE_PATTERNS_TO_BE_IGNORED:
# mark for later exclusion
version, date = (None, None)
# if we have a previous release already processed,
# compress the list of lines to a string
if current_release is not None:
- current_release.release_notes = u'\n'.join(current_release_notes)
+ current_release.release_notes = '\n'.join(current_release_notes)
# make a new release
current_release = ReleaseDto()
current_release.version = version
@@ -127,48 +124,46 @@ def _parse_news_file(self):
releases = [release for release in releases if release.version is not None]
return releases
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def _parse_release_line(self, line):
match = RELEASE_REGEXP.match(line)
if match:
return match.group('version'), match.group('date')
else:
- logger.warn(u'Failed parsing NEWS file: release line "%s" invalid', line)
+ logger.warn('Failed parsing NEWS file: release line "%s" invalid', line)
return None, None
-########################################################################
class ToDoView(StaticDocsView):
"""
Grab the TODO file from GIT master via Github API, parse it and send it back to the template
"""
template_name = "pages/documentation/todo.html"
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def get_context_data(self, **kwargs):
todo = self._get_todo()
context = super(ToDoView, self).get_context_data(**kwargs)
context['todo'] = todo
return context
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
@cache_function(CACHE_TIMEOUT_24HOURS)
def _get_todo(self):
self._fetch_file_via_github_api('TODO')
return self._parse_news_file()
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def _parse_news_file(self):
return self._file_contents
-########################################################################
class I18NStatisticsView(TemplateView):
template_name = "pages/i18n.html"
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
def get_context_data(self, **kwargs):
i18n_statistics = self._get_i18n_statistics()
context = super(I18NStatisticsView, self).get_context_data(**kwargs)
@@ -178,7 +173,7 @@ def get_context_data(self, **kwargs):
context['static_docs_geany_destination_url'] = settings.STATIC_DOCS_GEANY_DESTINATION_URL
return context
- #----------------------------------------------------------------------
+ # ----------------------------------------------------------------------
@cache_function(CACHE_TIMEOUT_1HOUR)
def _get_i18n_statistics(self):
filename = os.path.join(
--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).
More information about the Commits
mailing list