diff --git a/accounts/admin.py b/accounts/admin.py index 69be4f6..02eaf99 100644 --- a/accounts/admin.py +++ b/accounts/admin.py @@ -3,9 +3,9 @@ from django.contrib import admin class UserProfileAdmin(admin.ModelAdmin): - list_display = ('user', 'is_pro', 'stripe_id', 'gittip_username', - 'teams_beta_seen') - list_filter = ['teams_beta_seen', 'teams_beta_applied'] - search_fields = ('user__username', 'gittip_username',) + list_display = ("user", "is_pro", "stripe_id", "gittip_username", "teams_beta_seen") + list_filter = ["teams_beta_seen", "teams_beta_applied"] + search_fields = ("user__username", "gittip_username") + admin.site.register(UserProfile, UserProfileAdmin) diff --git a/accounts/management/commands/migrate_user_passwords.py b/accounts/management/commands/migrate_user_passwords.py index 737dcfc..5955a85 100644 --- a/accounts/management/commands/migrate_user_passwords.py +++ b/accounts/management/commands/migrate_user_passwords.py @@ -14,9 +14,9 @@ class Command(BaseCommand): self.stdout.write(u"Updating %s user passwords..." % users.count()) for user in users: - if user.password[0:3] == 'bc$': + if user.password[0:3] == "bc$": pw = user.password - new_password = pw[0:3].replace('bc$', 'bcrypt$') + pw[3:] + new_password = pw[0:3].replace("bc$", "bcrypt$") + pw[3:] user.password = new_password user.save() diff --git a/accounts/migrations/0001_initial.py b/accounts/migrations/0001_initial.py index cf88764..1a75705 100644 --- a/accounts/migrations/0001_initial.py +++ b/accounts/migrations/0001_initial.py @@ -7,36 +7,115 @@ from django.conf import settings class Migration(migrations.Migration): - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ] + dependencies = [migrations.swappable_dependency(settings.AUTH_USER_MODEL)] operations = [ migrations.CreateModel( - name='UserProfile', + name="UserProfile", fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('is_pro', models.BooleanField(default=False)), - ('teams_beta_seen', models.BooleanField(default=False)), - ('teams_beta_applied', models.BooleanField(default=False)), - ('pro_date', models.DateTimeField(null=True, blank=True)), - ('stripe_id', models.CharField(max_length=100, null=True, blank=True)), - ('has_gravatar', models.BooleanField(default=False)), - ('list_view', models.CharField(default=b'N', max_length=1, choices=[(b'N', b'Normal'), (b'C', b'Compact')])), - ('blog_title', models.CharField(max_length=250, null=True, blank=True)), - ('blog_theme', models.CharField(default=b'A', max_length=1, choices=[(b'D', b'Default'), (b'A', b'Pro Adams')])), - ('blog_domain', models.CharField(max_length=250, null=True, blank=True)), - ('default_editor', models.CharField(default=b'C', max_length=250, choices=[(b'C', b'CodeMirror'), (b'T', b'Textarea')])), - ('editor_theme', models.CharField(default=b'default', max_length=250, choices=[(b'default', b'Default'), (b'ambiance', b'Ambiance'), (b'blackboard', b'Blackboard'), (b'cobalt', b'Cobalt'), (b'eclipse', b'Eclipse'), (b'elegant', b'Elegant'), (b'erlang-dark', b'Erlang Dark'), (b'lesser-dark', b'Lesser Dark'), (b'monokai', b'Monokai'), (b'neat', b'Neat'), (b'night', b'Night'), (b'rubyblue', b'Ruby Blue'), (b'solarized dark', b'Solarized Dark'), (b'solarized light', b'Solarized Light'), (b'twilight', b'Twilight'), (b'vibrant-ink', b'Vibrant Ink'), (b'xq-dark', b'XQ Dark')])), - ('gittip_username', models.CharField(max_length=250, null=True, blank=True)), - ('disqus_shortname', models.CharField(max_length=250, null=True, blank=True)), - ('google_analytics_tracking_id', models.CharField(max_length=250, null=True, blank=True)), - ('gauges_site_id', models.CharField(max_length=250, null=True, blank=True)), - ('google_ad_client', models.CharField(max_length=250, null=True, blank=True)), - ('google_ad_slot', models.CharField(max_length=250, null=True, blank=True)), - ('google_ad_width', models.CharField(max_length=250, null=True, blank=True)), - ('google_ad_height', models.CharField(max_length=250, null=True, blank=True)), - ('user', models.ForeignKey(to=settings.AUTH_USER_MODEL, unique=True)), + ( + "id", + models.AutoField( + verbose_name="ID", + serialize=False, + auto_created=True, + primary_key=True, + ), + ), + ("is_pro", models.BooleanField(default=False)), + ("teams_beta_seen", models.BooleanField(default=False)), + ("teams_beta_applied", models.BooleanField(default=False)), + ("pro_date", models.DateTimeField(null=True, blank=True)), + ("stripe_id", models.CharField(max_length=100, null=True, blank=True)), + ("has_gravatar", models.BooleanField(default=False)), + ( + "list_view", + models.CharField( + default=b"N", + max_length=1, + choices=[(b"N", b"Normal"), (b"C", b"Compact")], + ), + ), + ("blog_title", models.CharField(max_length=250, null=True, blank=True)), + ( + "blog_theme", + models.CharField( + default=b"A", + max_length=1, + choices=[(b"D", b"Default"), (b"A", b"Pro Adams")], + ), + ), + ( + "blog_domain", + models.CharField(max_length=250, null=True, blank=True), + ), + ( + "default_editor", + models.CharField( + default=b"C", + max_length=250, + choices=[(b"C", b"CodeMirror"), (b"T", b"Textarea")], + ), + ), + ( + "editor_theme", + models.CharField( + default=b"default", + max_length=250, + choices=[ + (b"default", b"Default"), + (b"ambiance", b"Ambiance"), + (b"blackboard", b"Blackboard"), + (b"cobalt", b"Cobalt"), + (b"eclipse", b"Eclipse"), + (b"elegant", b"Elegant"), + (b"erlang-dark", b"Erlang Dark"), + (b"lesser-dark", b"Lesser Dark"), + (b"monokai", b"Monokai"), + (b"neat", b"Neat"), + (b"night", b"Night"), + (b"rubyblue", b"Ruby Blue"), + (b"solarized dark", b"Solarized Dark"), + (b"solarized light", b"Solarized Light"), + (b"twilight", b"Twilight"), + (b"vibrant-ink", b"Vibrant Ink"), + (b"xq-dark", b"XQ Dark"), + ], + ), + ), + ( + "gittip_username", + models.CharField(max_length=250, null=True, blank=True), + ), + ( + "disqus_shortname", + models.CharField(max_length=250, null=True, blank=True), + ), + ( + "google_analytics_tracking_id", + models.CharField(max_length=250, null=True, blank=True), + ), + ( + "gauges_site_id", + models.CharField(max_length=250, null=True, blank=True), + ), + ( + "google_ad_client", + models.CharField(max_length=250, null=True, blank=True), + ), + ( + "google_ad_slot", + models.CharField(max_length=250, null=True, blank=True), + ), + ( + "google_ad_width", + models.CharField(max_length=250, null=True, blank=True), + ), + ( + "google_ad_height", + models.CharField(max_length=250, null=True, blank=True), + ), + ("user", models.ForeignKey(to=settings.AUTH_USER_MODEL, unique=True)), ], - ), + ) ] diff --git a/accounts/migrations/0002_auto_20150724_2010.py b/accounts/migrations/0002_auto_20150724_2010.py index 6bca66a..55f584c 100644 --- a/accounts/migrations/0002_auto_20150724_2010.py +++ b/accounts/migrations/0002_auto_20150724_2010.py @@ -7,14 +7,12 @@ from django.conf import settings class Migration(migrations.Migration): - dependencies = [ - ('accounts', '0001_initial'), - ] + dependencies = [("accounts", "0001_initial")] operations = [ migrations.AlterField( - model_name='userprofile', - name='user', + model_name="userprofile", + name="user", field=models.OneToOneField(to=settings.AUTH_USER_MODEL), - ), + ) ] diff --git a/accounts/migrations/0003_auto_20160512_1058.py b/accounts/migrations/0003_auto_20160512_1058.py index a935178..5f0d1d9 100644 --- a/accounts/migrations/0003_auto_20160512_1058.py +++ b/accounts/migrations/0003_auto_20160512_1058.py @@ -6,29 +6,59 @@ from django.db import models, migrations class Migration(migrations.Migration): - dependencies = [ - ('accounts', '0002_auto_20150724_2010'), - ] + dependencies = [("accounts", "0002_auto_20150724_2010")] operations = [ migrations.AlterField( - model_name='userprofile', - name='blog_theme', - field=models.CharField(max_length=1, choices=[('D', 'Default'), ('A', 'Pro Adams')], default='A'), + model_name="userprofile", + name="blog_theme", + field=models.CharField( + max_length=1, + choices=[("D", "Default"), ("A", "Pro Adams")], + default="A", + ), ), migrations.AlterField( - model_name='userprofile', - name='default_editor', - field=models.CharField(max_length=250, choices=[('C', 'CodeMirror'), ('T', 'Textarea')], default='C'), + model_name="userprofile", + name="default_editor", + field=models.CharField( + max_length=250, + choices=[("C", "CodeMirror"), ("T", "Textarea")], + default="C", + ), ), migrations.AlterField( - model_name='userprofile', - name='editor_theme', - field=models.CharField(max_length=250, choices=[('default', 'Default'), ('ambiance', 'Ambiance'), ('blackboard', 'Blackboard'), ('cobalt', 'Cobalt'), ('eclipse', 'Eclipse'), ('elegant', 'Elegant'), ('erlang-dark', 'Erlang Dark'), ('lesser-dark', 'Lesser Dark'), ('monokai', 'Monokai'), ('neat', 'Neat'), ('night', 'Night'), ('rubyblue', 'Ruby Blue'), ('solarized dark', 'Solarized Dark'), ('solarized light', 'Solarized Light'), ('twilight', 'Twilight'), ('vibrant-ink', 'Vibrant Ink'), ('xq-dark', 'XQ Dark')], default='default'), + model_name="userprofile", + name="editor_theme", + field=models.CharField( + max_length=250, + choices=[ + ("default", "Default"), + ("ambiance", "Ambiance"), + ("blackboard", "Blackboard"), + ("cobalt", "Cobalt"), + ("eclipse", "Eclipse"), + ("elegant", "Elegant"), + ("erlang-dark", "Erlang Dark"), + ("lesser-dark", "Lesser Dark"), + ("monokai", "Monokai"), + ("neat", "Neat"), + ("night", "Night"), + ("rubyblue", "Ruby Blue"), + ("solarized dark", "Solarized Dark"), + ("solarized light", "Solarized Light"), + ("twilight", "Twilight"), + ("vibrant-ink", "Vibrant Ink"), + ("xq-dark", "XQ Dark"), + ], + default="default", + ), ), migrations.AlterField( - model_name='userprofile', - name='list_view', - field=models.CharField(max_length=1, choices=[('N', 'Normal'), ('C', 'Compact')], default='N'), + model_name="userprofile", + name="list_view", + field=models.CharField( + max_length=1, choices=[("N", "Normal"), ("C", "Compact")], default="N" + ), ), ] diff --git a/accounts/models.py b/accounts/models.py index 8020ee8..2e5bfe6 100644 --- a/accounts/models.py +++ b/accounts/models.py @@ -9,39 +9,30 @@ from teams.models import Team class UserProfile(models.Model): - LIST_VIEW_CHOICES = ( - ('N', 'Normal'), - ('C', 'Compact'), - ) + LIST_VIEW_CHOICES = (("N", "Normal"), ("C", "Compact")) - EDITOR_CHOICES = ( - ('C', 'CodeMirror'), - ('T', 'Textarea'), - ) + EDITOR_CHOICES = (("C", "CodeMirror"), ("T", "Textarea")) - THEME_CHOICES = ( - ('D', 'Default'), - ('A', 'Pro Adams'), - ) + THEME_CHOICES = (("D", "Default"), ("A", "Pro Adams")) EDITOR_THEME_CHOICES = ( - ('default', 'Default'), - ('ambiance', 'Ambiance'), - ('blackboard', 'Blackboard'), - ('cobalt', 'Cobalt'), - ('eclipse', 'Eclipse'), - ('elegant', 'Elegant'), - ('erlang-dark', 'Erlang Dark'), - ('lesser-dark', 'Lesser Dark'), - ('monokai', 'Monokai'), - ('neat', 'Neat'), - ('night', 'Night'), - ('rubyblue', 'Ruby Blue'), - ('solarized dark', 'Solarized Dark'), - ('solarized light', 'Solarized Light'), - ('twilight', 'Twilight'), - ('vibrant-ink', 'Vibrant Ink'), - ('xq-dark', 'XQ Dark'), + ("default", "Default"), + ("ambiance", "Ambiance"), + ("blackboard", "Blackboard"), + ("cobalt", "Cobalt"), + ("eclipse", "Eclipse"), + ("elegant", "Elegant"), + ("erlang-dark", "Erlang Dark"), + ("lesser-dark", "Lesser Dark"), + ("monokai", "Monokai"), + ("neat", "Neat"), + ("night", "Night"), + ("rubyblue", "Ruby Blue"), + ("solarized dark", "Solarized Dark"), + ("solarized light", "Solarized Light"), + ("twilight", "Twilight"), + ("vibrant-ink", "Vibrant Ink"), + ("xq-dark", "XQ Dark"), ) # User @@ -52,27 +43,35 @@ class UserProfile(models.Model): pro_date = models.DateTimeField(blank=True, null=True) stripe_id = models.CharField(max_length=100, null=True, blank=True) has_gravatar = models.BooleanField(default=False) - list_view = models.CharField(max_length=1, null=False, blank=False, - default='N', choices=LIST_VIEW_CHOICES) + list_view = models.CharField( + max_length=1, null=False, blank=False, default="N", choices=LIST_VIEW_CHOICES + ) # Blog blog_title = models.CharField(max_length=250, null=True, blank=True) - blog_theme = models.CharField(max_length=1, null=False, blank=False, - default='A', choices=THEME_CHOICES) + blog_theme = models.CharField( + max_length=1, null=False, blank=False, default="A", choices=THEME_CHOICES + ) blog_domain = models.CharField(max_length=250, null=True, blank=True) # Editor - default_editor = models.CharField(max_length=250, null=False, blank=False, - default='C', choices=EDITOR_CHOICES) - editor_theme = models.CharField(max_length=250, null=False, blank=False, - default='default', - choices=EDITOR_THEME_CHOICES) + default_editor = models.CharField( + max_length=250, null=False, blank=False, default="C", choices=EDITOR_CHOICES + ) + editor_theme = models.CharField( + max_length=250, + null=False, + blank=False, + default="default", + choices=EDITOR_THEME_CHOICES, + ) # Services and Analytics gittip_username = models.CharField(max_length=250, null=True, blank=True) disqus_shortname = models.CharField(max_length=250, null=True, blank=True) - google_analytics_tracking_id = models.CharField(max_length=250, null=True, - blank=True) + google_analytics_tracking_id = models.CharField( + max_length=250, null=True, blank=True + ) gauges_site_id = models.CharField(max_length=250, null=True, blank=True) # Google Ads @@ -82,36 +81,34 @@ class UserProfile(models.Model): google_ad_height = models.CharField(max_length=250, null=True, blank=True) def get_blog_posts(self): - return Snipt.objects.filter(user=self.user, blog_post=True, - public=True) + return Snipt.objects.filter(user=self.user, blog_post=True, public=True) def get_primary_blog_domain(self): if not self.blog_domain: return None else: - return self.blog_domain.split(' ')[0] + return self.blog_domain.split(" ")[0] def get_user_profile_url(self): # If the user has a blog domain, use that. if self.blog_domain: - url = 'http://{}'.format(self.get_primary_blog_domain()) + url = "http://{}".format(self.get_primary_blog_domain()) # Otherwise, if they have blog posts, use their Snipt blog URL. elif self.get_blog_posts(): - url = 'https://{}.snippets.siftie.com/'.format(self.user.username) + url = "https://{}.snippets.siftie.com/".format(self.user.username) # Otherwise, use their regular Snipt profile page. else: - url = 'https://snippets.siftie.com/{}/'.format(self.user.username) + url = "https://snippets.siftie.com/{}/".format(self.user.username) return url def has_public_snipts(self): - return True \ - if Snipt.objects.filter(user=self, - public=True).count() > 0 \ - else False + return ( + True if Snipt.objects.filter(user=self, public=True).count() > 0 else False + ) @property def is_a_team(self): @@ -127,14 +124,16 @@ class UserProfile(models.Model): @property def has_teams(self): - if (len(self.teams()) > 0): + if len(self.teams()) > 0: return True else: return False def get_account_age(self): - delta = datetime.now().replace(tzinfo=None) - \ - self.user.date_joined.replace(tzinfo=None) + delta = datetime.now().replace(tzinfo=None) - self.user.date_joined.replace( + tzinfo=None + ) return delta.days + User.profile = property(lambda u: UserProfile.objects.get_or_create(user=u)[0]) diff --git a/accounts/urls.py b/accounts/urls.py index 074e975..9960be9 100644 --- a/accounts/urls.py +++ b/accounts/urls.py @@ -3,6 +3,6 @@ from django.conf.urls import url urlpatterns = [ - url(r'^stats/$', views.stats, name='account-stats'), - url(r'^', views.account, name='account-detail') + url(r"^stats/$", views.stats, name="account-stats"), + url(r"^", views.account, name="account-detail"), ] diff --git a/accounts/views.py b/accounts/views.py index 10061a6..3bb8543 100644 --- a/accounts/views.py +++ b/accounts/views.py @@ -5,17 +5,15 @@ from snipts.models import Snipt @login_required -@render_to('account.html') +@render_to("account.html") def account(request): return {} @login_required -@render_to('stats.html') +@render_to("stats.html") def stats(request): - snipts = Snipt.objects.filter(user=request.user).order_by('-views') + snipts = Snipt.objects.filter(user=request.user).order_by("-views") - return { - 'snipts': snipts - } + return {"snipts": snipts} diff --git a/blogs/middleware.py b/blogs/middleware.py index 785340c..5583c75 100644 --- a/blogs/middleware.py +++ b/blogs/middleware.py @@ -8,43 +8,43 @@ class BlogMiddleware: def process_request(self, request): request.blog_user = None - host = request.META.get('HTTP_HOST', '') - host_s = host.replace('www.', '').split('.') + host = request.META.get("HTTP_HOST", "") + host_s = host.replace("www.", "").split(".") - if host != 'snippets.siftie.com' and \ - host != 'snipt.localhost' and \ - host != 'local.snippets.siftie.com': + if ( + host != "snippets.siftie.com" + and host != "snipt.localhost" + and host != "local.snippets.siftie.com" + ): if len(host_s) > 2: - if host_s[1] == 'snipt': + if host_s[1] == "snipt": - blog_user = ''.join(host_s[:-2]) + blog_user = "".join(host_s[:-2]) - if '-' in blog_user: - request.blog_user = \ - get_object_or_None(User, - username__iexact=blog_user) + if "-" in blog_user: + request.blog_user = get_object_or_None( + User, username__iexact=blog_user + ) if request.blog_user is None: - request.blog_user = \ - get_object_or_404(User, - username__iexact=blog_user - .replace('-', '_')) + request.blog_user = get_object_or_404( + User, username__iexact=blog_user.replace("-", "_") + ) else: - request.blog_user = \ - get_object_or_404(User, username__iexact=blog_user) + request.blog_user = get_object_or_404( + User, username__iexact=blog_user + ) if request.blog_user is None: pro_users = User.objects.filter(userprofile__is_pro=True) for pro_user in pro_users: if pro_user.profile.blog_domain: - if host in pro_user.profile.blog_domain.split(' '): + if host in pro_user.profile.blog_domain.split(" "): request.blog_user = pro_user - if host != \ - pro_user.profile.get_primary_blog_domain(): + if host != pro_user.profile.get_primary_blog_domain(): return HttpResponseRedirect( - 'http://' + - pro_user - .profile - .get_primary_blog_domain()) + "http://" + + pro_user.profile.get_primary_blog_domain() + ) diff --git a/blogs/urls.py b/blogs/urls.py index bfd0b63..c2776eb 100644 --- a/blogs/urls.py +++ b/blogs/urls.py @@ -2,4 +2,4 @@ from blogs import views from django.conf.urls import url -urlpatterns = [url(r'^$', views.blog, name='blog')] +urlpatterns = [url(r"^$", views.blog, name="blog")] diff --git a/blogs/views.py b/blogs/views.py index a12c8e4..fdf75ec 100644 --- a/blogs/views.py +++ b/blogs/views.py @@ -4,10 +4,7 @@ from annoying.functions import get_object_or_None from django.shortcuts import get_object_or_404, render from snipts.models import Snipt -THEME_CHOICES = { - 'D': 'blogs/themes/default/', - 'A': 'blogs/themes/pro-adams/', -} +THEME_CHOICES = {"D": "blogs/themes/default/", "A": "blogs/themes/pro-adams/"} def blog_list(request, username_or_custom_slug=None): @@ -15,83 +12,95 @@ def blog_list(request, username_or_custom_slug=None): if username_or_custom_slug: return blog_post(request, username_or_custom_slug) - snipts = Snipt.objects.filter(user=request.blog_user, - blog_post=True, - public=True, - publish_date__lte=datetime.datetime.now()) \ - .order_by('-publish_date') \ - .exclude(title__iexact='Homepage') \ - .exclude(title__iexact='Work') + snipts = ( + Snipt.objects.filter( + user=request.blog_user, + blog_post=True, + public=True, + publish_date__lte=datetime.datetime.now(), + ) + .order_by("-publish_date") + .exclude(title__iexact="Homepage") + .exclude(title__iexact="Work") + ) - normal_snipts = Snipt.objects.filter(blog_post=False, - user=request.blog_user, - public=True) \ - .order_by('-created') - normal_snipts = normal_snipts.exclude(title__in=['']) - normal_snipts = normal_snipts.exclude(tags__name__in=['tmp']) + normal_snipts = Snipt.objects.filter( + blog_post=False, user=request.blog_user, public=True + ).order_by("-created") + normal_snipts = normal_snipts.exclude(title__in=[""]) + normal_snipts = normal_snipts.exclude(tags__name__in=["tmp"]) normal_snipts = normal_snipts[:3] - sidebar = get_object_or_None(Snipt, user=request.blog_user, - title='Sidebar', blog_post=True) - header = get_object_or_None(Snipt, user=request.blog_user, title='Header', - blog_post=True) - custom_css = get_object_or_None(Snipt, user=request.blog_user, title='CSS', - lexer='css', blog_post=True) + sidebar = get_object_or_None( + Snipt, user=request.blog_user, title="Sidebar", blog_post=True + ) + header = get_object_or_None( + Snipt, user=request.blog_user, title="Header", blog_post=True + ) + custom_css = get_object_or_None( + Snipt, user=request.blog_user, title="CSS", lexer="css", blog_post=True + ) context = { - 'blog_user': request.blog_user, - 'custom_css': custom_css, - 'has_snipts': True, - 'header': header, - 'normal_snipts': normal_snipts, - 'public': True, - 'sidebar': sidebar, - 'snipts': snipts, + "blog_user": request.blog_user, + "custom_css": custom_css, + "has_snipts": True, + "header": header, + "normal_snipts": normal_snipts, + "public": True, + "sidebar": sidebar, + "snipts": snipts, } - if 'rss' in request.GET: - context['snipts'] = context['snipts'][:20] + if "rss" in request.GET: + context["snipts"] = context["snipts"][:20] return rss(request, context) template = THEME_CHOICES[request.blog_user.profile.blog_theme] - template = '{}/list.html'.format(template) + template = "{}/list.html".format(template) - return render( - request, - template, - context, - ) + return render(request, template, context) def blog_post(request, username_or_custom_slug): - snipt = get_object_or_404(Snipt, user=request.blog_user, - blog_post=True, - public=True, - publish_date__lte=datetime.datetime.now(), - slug=username_or_custom_slug) + snipt = get_object_or_404( + Snipt, + user=request.blog_user, + blog_post=True, + public=True, + publish_date__lte=datetime.datetime.now(), + slug=username_or_custom_slug, + ) - snipts = Snipt.objects.filter(user=request.blog_user, - blog_post=True, - public=True, - publish_date__lte=datetime.datetime.now()) \ - .order_by('-publish_date') \ - .exclude(title__iexact='Homepage') \ - .exclude(title__iexact='Work') + snipts = ( + Snipt.objects.filter( + user=request.blog_user, + blog_post=True, + public=True, + publish_date__lte=datetime.datetime.now(), + ) + .order_by("-publish_date") + .exclude(title__iexact="Homepage") + .exclude(title__iexact="Work") + ) - sidebar = get_object_or_None(Snipt, user=request.blog_user, - title='Sidebar', blog_post=True) - header = get_object_or_None(Snipt, user=request.blog_user, title='Header', - blog_post=True) - custom_css = get_object_or_None(Snipt, user=request.blog_user, title='CSS', - lexer='css', blog_post=True) + sidebar = get_object_or_None( + Snipt, user=request.blog_user, title="Sidebar", blog_post=True + ) + header = get_object_or_None( + Snipt, user=request.blog_user, title="Header", blog_post=True + ) + custom_css = get_object_or_None( + Snipt, user=request.blog_user, title="CSS", lexer="css", blog_post=True + ) - normal_snipts = Snipt.objects.filter(blog_post=False, - user=request.blog_user, - public=True).order_by('-created') - normal_snipts = normal_snipts.exclude(title__in=['']) - normal_snipts = normal_snipts.exclude(tags__name__in=['tmp']) + normal_snipts = Snipt.objects.filter( + blog_post=False, user=request.blog_user, public=True + ).order_by("-created") + normal_snipts = normal_snipts.exclude(title__in=[""]) + normal_snipts = normal_snipts.exclude(tags__name__in=["tmp"]) normal_snipts = normal_snipts[:3] if snipt.user != request.user: @@ -99,25 +108,29 @@ def blog_post(request, username_or_custom_slug): snipt.save() context = { - 'blog_user': request.blog_user, - 'custom_css': custom_css, - 'detail': True, - 'has_snipts': True, - 'header': header, - 'normal_snipts': normal_snipts, - 'public': True, - 'sidebar': sidebar, - 'snipt': snipt, - 'snipts': snipts, + "blog_user": request.blog_user, + "custom_css": custom_css, + "detail": True, + "has_snipts": True, + "header": header, + "normal_snipts": normal_snipts, + "public": True, + "sidebar": sidebar, + "snipt": snipt, + "snipts": snipts, } template = THEME_CHOICES[request.blog_user.profile.blog_theme] - template = '{}/post.html'.format(template) + template = "{}/post.html".format(template) return render(request, template, context) def rss(request, context): - return render(request, 'blogs/themes/default/rss.xml', context, - content_type="application/rss+xml") + return render( + request, + "blogs/themes/default/rss.xml", + context, + content_type="application/rss+xml", + ) diff --git a/settings.py b/settings.py index b2a7219..cbe2db8 100644 --- a/settings.py +++ b/settings.py @@ -3,134 +3,132 @@ from urllib.parse import urlparse import dj_database_url import os -if 'DATABASE_URL' in os.environ: - DATABASES = {'default': dj_database_url.config()} +if "DATABASE_URL" in os.environ: + DATABASES = {"default": dj_database_url.config()} -ABSOLUTE_URL_OVERRIDES = {'auth.user': lambda u: "/%s/" % u.username} +ABSOLUTE_URL_OVERRIDES = {"auth.user": lambda u: "/%s/" % u.username} ACCOUNT_ACTIVATION_DAYS = 0 -ADMINS = (('Siftie', 'team@siftie.com'),) -ALLOWED_HOSTS = ['*'] -AUTH_PROFILE_MODULE = 'accounts.UserProfile' -AUTHENTICATION_BACKENDS = ('utils.backends.EmailOrUsernameModelBackend',) +ADMINS = (("Siftie", "team@siftie.com"),) +ALLOWED_HOSTS = ["*"] +AUTH_PROFILE_MODULE = "accounts.UserProfile" +AUTHENTICATION_BACKENDS = ("utils.backends.EmailOrUsernameModelBackend",) BASE_PATH = os.path.dirname(__file__) -CSRF_COOKIE_SECURE = True if 'USE_SSL' in os.environ else False +CSRF_COOKIE_SECURE = True if "USE_SSL" in os.environ else False CORS_ORIGIN_ALLOW_ALL = True -DEBUG = True if 'DEBUG' in os.environ else False -DEFAULT_FROM_EMAIL = os.environ.get('POSTMARK_EMAIL', 'support@siftie.com') -EMAIL_BACKEND = 'postmark.django_backend.EmailBackend' -HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor' -INTERNAL_IPS = ('127.0.0.1',) -LANGUAGE_CODE = 'en-us' -LOGIN_REDIRECT_URL = '/login-redirect/' -LOGIN_URL = '/login/' -LOGOUT_URL = '/logout/' +DEBUG = True if "DEBUG" in os.environ else False +DEFAULT_FROM_EMAIL = os.environ.get("POSTMARK_EMAIL", "support@siftie.com") +EMAIL_BACKEND = "postmark.django_backend.EmailBackend" +HAYSTACK_SIGNAL_PROCESSOR = "haystack.signals.RealtimeSignalProcessor" +INTERNAL_IPS = ("127.0.0.1",) +LANGUAGE_CODE = "en-us" +LOGIN_REDIRECT_URL = "/login-redirect/" +LOGIN_URL = "/login/" +LOGOUT_URL = "/logout/" MANAGERS = ADMINS -MEDIA_ROOT = os.path.join(BASE_PATH, 'media/uploads') -MEDIA_URL = '/media/uploads/' -MESSAGE_STORAGE = 'django.contrib.messages.storage.cookie.CookieStorage' +MEDIA_ROOT = os.path.join(BASE_PATH, "media/uploads") +MEDIA_URL = "/media/uploads/" +MESSAGE_STORAGE = "django.contrib.messages.storage.cookie.CookieStorage" PASSWORD_HASHERS = ( - 'django.contrib.auth.hashers.BCryptPasswordHasher', - 'django.contrib.auth.hashers.BCryptSHA256PasswordHasher', - 'django.contrib.auth.hashers.PBKDF2PasswordHasher', - 'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher', - 'django.contrib.auth.hashers.SHA1PasswordHasher', - 'django.contrib.auth.hashers.MD5PasswordHasher', - 'django.contrib.auth.hashers.CryptPasswordHasher', + "django.contrib.auth.hashers.BCryptPasswordHasher", + "django.contrib.auth.hashers.BCryptSHA256PasswordHasher", + "django.contrib.auth.hashers.PBKDF2PasswordHasher", + "django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher", + "django.contrib.auth.hashers.SHA1PasswordHasher", + "django.contrib.auth.hashers.MD5PasswordHasher", + "django.contrib.auth.hashers.CryptPasswordHasher", ) -POSTMARK_API_KEY = os.environ.get('POSTMARK_API_KEY', '') +POSTMARK_API_KEY = os.environ.get("POSTMARK_API_KEY", "") PROJECT_PATH = os.path.abspath(os.path.dirname(__file__)) REGISTRATION_EMAIL_HTML = False -ROOT_URLCONF = 'urls' -SECRET_KEY = os.environ.get('SECRET_KEY', 'changeme') -SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') -SECURE_SSL_REDIRECT = True if 'USE_SSL' in os.environ else False +ROOT_URLCONF = "urls" +SECRET_KEY = os.environ.get("SECRET_KEY", "changeme") +SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https") +SECURE_SSL_REDIRECT = True if "USE_SSL" in os.environ else False SEND_BROKEN_LINK_EMAILS = False -SERVER_EMAIL = os.environ.get('POSTMARK_EMAIL', 'support@siftie.com') +SERVER_EMAIL = os.environ.get("POSTMARK_EMAIL", "support@siftie.com") SESSION_COOKIE_AGE = 15801100 -SESSION_COOKIE_SECURE = True if 'USE_SSL' in os.environ else False +SESSION_COOKIE_SECURE = True if "USE_SSL" in os.environ else False SITE_ID = 1 -STATICFILES_DIRS = (os.path.join(BASE_PATH, 'media'),) -STATICFILES_FINDERS = ('django.contrib.staticfiles.finders.FileSystemFinder', - 'django.contrib.staticfiles.finders.AppDirectoriesFinder') -STATICFILES_STORAGE = 'whitenoise.django.GzipManifestStaticFilesStorage' -STATIC_ROOT = os.path.join(BASE_PATH, 'static') -STATIC_URL = '/static/' +STATICFILES_DIRS = (os.path.join(BASE_PATH, "media"),) +STATICFILES_FINDERS = ( + "django.contrib.staticfiles.finders.FileSystemFinder", + "django.contrib.staticfiles.finders.AppDirectoriesFinder", +) +STATICFILES_STORAGE = "whitenoise.django.GzipManifestStaticFilesStorage" +STATIC_ROOT = os.path.join(BASE_PATH, "static") +STATIC_URL = "/static/" TASTYPIE_CANNED_ERROR = """There was an error with your request. The site developers have a record of this error, please email support@siftie.com and we'll help you out.""" TEMPLATES = [ { - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [os.path.join(PROJECT_PATH, 'templates')], - 'APP_DIRS': True, - 'OPTIONS': { - 'context_processors': [ - 'django.template.context_processors.debug', - 'django.template.context_processors.request', - 'django.template.context_processors.static', - 'django.contrib.auth.context_processors.auth', - 'django.contrib.messages.context_processors.messages', - ], + "BACKEND": "django.template.backends.django.DjangoTemplates", + "DIRS": [os.path.join(PROJECT_PATH, "templates")], + "APP_DIRS": True, + "OPTIONS": { + "context_processors": [ + "django.template.context_processors.debug", + "django.template.context_processors.request", + "django.template.context_processors.static", + "django.contrib.auth.context_processors.auth", + "django.contrib.messages.context_processors.messages", + ] }, - }, + } ] -TIME_ZONE = 'America/New_York' -USE_HTTPS = True if 'USE_SSL' in os.environ else False +TIME_ZONE = "America/New_York" +USE_HTTPS = True if "USE_SSL" in os.environ else False USE_I18N = True USE_L10N = True USE_TZ = True INSTALLED_APPS = ( - 'accounts', - 'blogs', - 'corsheaders', - 'django.contrib.admin', - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.humanize', - 'django.contrib.messages', - 'django.contrib.sessions', - 'django.contrib.sites', - 'django.contrib.staticfiles', - 'django_extensions', - 'gunicorn', - 'haystack', - 'markdown_deux', - 'pagination', - 'postmark', - 'registration', - 'snipts', - 'storages', - 'taggit', - 'tastypie', - 'teams', - 'user-admin', - 'utils', + "accounts", + "blogs", + "corsheaders", + "django.contrib.admin", + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.humanize", + "django.contrib.messages", + "django.contrib.sessions", + "django.contrib.sites", + "django.contrib.staticfiles", + "django_extensions", + "gunicorn", + "haystack", + "markdown_deux", + "pagination", + "postmark", + "registration", + "snipts", + "storages", + "taggit", + "tastypie", + "teams", + "user-admin", + "utils", ) LOGGING = { - 'version': 1, - 'disable_existing_loggers': False, - 'filters': { - 'require_debug_false': { - '()': 'django.utils.log.RequireDebugFalse' - } - }, - 'handlers': {}, - 'loggers': {} + "version": 1, + "disable_existing_loggers": False, + "filters": {"require_debug_false": {"()": "django.utils.log.RequireDebugFalse"}}, + "handlers": {}, + "loggers": {}, } MIDDLEWARE_CLASSES = ( - 'django.middleware.security.SecurityMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.middleware.clickjacking.XFrameOptionsMiddleware', - 'corsheaders.middleware.CorsMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'pagination.middleware.PaginationMiddleware', - 'blogs.middleware.BlogMiddleware', + "django.middleware.security.SecurityMiddleware", + "django.middleware.csrf.CsrfViewMiddleware", + "django.middleware.clickjacking.XFrameOptionsMiddleware", + "corsheaders.middleware.CorsMiddleware", + "django.middleware.common.CommonMiddleware", + "django.contrib.sessions.middleware.SessionMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", + "django.contrib.messages.middleware.MessageMiddleware", + "pagination.middleware.PaginationMiddleware", + "blogs.middleware.BlogMiddleware", ) try: diff --git a/snipts/admin.py b/snipts/admin.py index 88e13d1..747dbeb 100644 --- a/snipts/admin.py +++ b/snipts/admin.py @@ -3,29 +3,42 @@ from snipts.models import Favorite, Snipt, SniptLogEntry class SniptAdmin(admin.ModelAdmin): - readonly_fields = ('last_user_saved', 'user',) - list_display = ('title', 'slug', 'views', 'favs', 'user', 'lexer', - 'public', 'blog_post', 'created', 'modified', - 'publish_date') - list_filter = ('blog_post',) - search_fields = ('title', 'slug', 'user__username', 'lexer', 'id', 'key',) - ordering = ('-created',) - prepopulated_fields = {'slug': ('title',)} + readonly_fields = ("last_user_saved", "user") + list_display = ( + "title", + "slug", + "views", + "favs", + "user", + "lexer", + "public", + "blog_post", + "created", + "modified", + "publish_date", + ) + list_filter = ("blog_post",) + search_fields = ("title", "slug", "user__username", "lexer", "id", "key") + ordering = ("-created",) + prepopulated_fields = {"slug": ("title",)} + admin.site.register(Snipt, SniptAdmin) class SniptLogEntryAdmin(admin.ModelAdmin): - readonly_fields = ('snipt', 'user',) - list_display = ('snipt_name', 'user', 'created', 'modified') + readonly_fields = ("snipt", "user") + list_display = ("snipt_name", "user", "created", "modified") + admin.site.register(SniptLogEntry, SniptLogEntryAdmin) class FavoriteAdmin(admin.ModelAdmin): - readonly_fields = ('snipt', 'user',) - list_display = ('snipt', 'user', 'created',) - search_fields = ('snipt', 'user',) - ordering = ('-created',) + readonly_fields = ("snipt", "user") + list_display = ("snipt", "user", "created") + search_fields = ("snipt", "user") + ordering = ("-created",) + admin.site.register(Favorite, FavoriteAdmin) diff --git a/snipts/api.py b/snipts/api.py index 2762466..d9d3816 100644 --- a/snipts/api.py +++ b/snipts/api.py @@ -139,11 +139,10 @@ class PrivateUserAuthorization(Authorization): class FavoriteValidation(Validation): def is_valid(self, bundle, request=None): errors = {} - snipt = bundle.data['snipt'] + snipt = bundle.data["snipt"] - if Favorite.objects.filter(user=bundle.request.user, - snipt=snipt).count(): - errors = 'User has already favorited this snipt.' + if Favorite.objects.filter(user=bundle.request.user, snipt=snipt).count(): + errors = "User has already favorited this snipt." return errors @@ -152,8 +151,8 @@ class SniptValidation(Validation): def is_valid(self, bundle, request=None): errors = {} - if (len(bundle.data['title']) > 255): - errors = 'Title must be 255 characters or less.' + if len(bundle.data["title"]) > 255: + errors = "Title must be 255 characters or less." return errors @@ -164,10 +163,12 @@ class UserProfileValidation(Validation): for field in bundle.data: if bundle.data[field]: - if not re.match('^[ A-Za-z0-9\/\@\._-]*$', bundle.data[field]): - errors[field] = ('Only spaces, letters, numbers, ' - 'underscores, dashes, periods, forward ' - 'slashes, and "at sign" are valid.') + if not re.match("^[ A-Za-z0-9\/\@\._-]*$", bundle.data[field]): + errors[field] = ( + "Only spaces, letters, numbers, " + "underscores, dashes, periods, forward " + 'slashes, and "at sign" are valid.' + ) return errors @@ -175,33 +176,33 @@ class UserProfileValidation(Validation): class PublicUserResource(ModelResource): class Meta: queryset = User.objects.all() - resource_name = 'user' - fields = ['id', 'username'] + resource_name = "user" + fields = ["id", "username"] include_absolute_url = True - allowed_methods = ['get'] - filtering = {'username': ['contains', 'exact']} + allowed_methods = ["get"] + filtering = {"username": ["contains", "exact"]} max_limit = 200 cache = SimpleCache() def dehydrate(self, bundle): - bundle.data['snipts'] = '/api/public/snipt/?user=%d' % bundle.obj.id - bundle.data['email_md5'] = hashlib \ - .md5(bundle.obj.email.lower().encode('utf-8')) \ - .hexdigest() - bundle.data['snipts_count'] = Snipt.objects.filter(user=bundle.obj.id, - public=True).count() + bundle.data["snipts"] = "/api/public/snipt/?user=%d" % bundle.obj.id + bundle.data["email_md5"] = hashlib.md5( + bundle.obj.email.lower().encode("utf-8") + ).hexdigest() + bundle.data["snipts_count"] = Snipt.objects.filter( + user=bundle.obj.id, public=True + ).count() return bundle class PublicTagResource(ModelResource): class Meta: queryset = Tag.objects.filter() - queryset = queryset.annotate( - count=models.Count('taggit_taggeditem_items__id')) - queryset = queryset.order_by('-count', 'name') - resource_name = 'tag' - fields = ['id', 'name'] - allowed_methods = ['get'] + queryset = queryset.annotate(count=models.Count("taggit_taggeditem_items__id")) + queryset = queryset.order_by("-count", "name") + resource_name = "tag" + fields = ["id", "name"] + allowed_methods = ["get"] max_limit = 200 cache = SimpleCache() @@ -211,60 +212,74 @@ class PublicTagResource(ModelResource): orm_filters = super(PublicTagResource, self).build_filters(filters) - if 'q' in filters: - orm_filters['slug'] = filters['q'] + if "q" in filters: + orm_filters["slug"] = filters["q"] return orm_filters def dehydrate(self, bundle): - bundle.data['absolute_url'] = '/public/tag/%s/' % bundle.obj.slug - bundle.data['snipts'] = '/api/public/snipt/?tag=%d' % bundle.obj.id + bundle.data["absolute_url"] = "/public/tag/%s/" % bundle.obj.slug + bundle.data["snipts"] = "/api/public/snipt/?tag=%d" % bundle.obj.id return bundle class PublicSniptResource(ModelResource): - user = fields.ForeignKey(PublicUserResource, 'user', full=True) - tags = fields.ToManyField(PublicTagResource, 'tags', related_name='tag', - full=True) + user = fields.ForeignKey(PublicUserResource, "user", full=True) + tags = fields.ToManyField(PublicTagResource, "tags", related_name="tag", full=True) class Meta: - queryset = Snipt.objects.filter(public=True).order_by('-created') - resource_name = 'snipt' - fields = ['id', 'title', 'slug', 'lexer', 'code', 'description', - 'line_count', 'stylized', 'created', 'modified', - 'publish_date', 'blog_post', 'meta'] + queryset = Snipt.objects.filter(public=True).order_by("-created") + resource_name = "snipt" + fields = [ + "id", + "title", + "slug", + "lexer", + "code", + "description", + "line_count", + "stylized", + "created", + "modified", + "publish_date", + "blog_post", + "meta", + ] include_absolute_url = True - allowed_methods = ['get'] - filtering = {'user': 'exact', 'blog_post': 'exact'} - ordering = ['created', 'modified'] + allowed_methods = ["get"] + filtering = {"user": "exact", "blog_post": "exact"} + ordering = ["created", "modified"] max_limit = 200 cache = SimpleCache() def dehydrate(self, bundle): - bundle.data['embed_url'] = bundle.obj.get_embed_url() - bundle.data['raw_url'] = bundle.obj.get_raw_url() - bundle.data['full_absolute_url'] = bundle.obj.get_full_absolute_url() - bundle.data['description_rendered'] = \ - linebreaksbr(urlize(bundle.obj.description)) + bundle.data["embed_url"] = bundle.obj.get_embed_url() + bundle.data["raw_url"] = bundle.obj.get_raw_url() + bundle.data["full_absolute_url"] = bundle.obj.get_full_absolute_url() + bundle.data["description_rendered"] = linebreaksbr( + urlize(bundle.obj.description) + ) log_entries = bundle.obj.sniptlogentry_set.all() bundle_log_entries = [] for entry in log_entries: - bundle_log_entries.append({ - 'created': entry.created, - 'user': entry.user, - 'code': entry.code, - 'diff': entry.diff - }) + bundle_log_entries.append( + { + "created": entry.created, + "user": entry.user, + "code": entry.code, + "diff": entry.diff, + } + ) - bundle.data['log_entries'] = bundle_log_entries + bundle.data["log_entries"] = bundle_log_entries - if 'omit_code' in bundle.request.GET: - del bundle.data['code'] + if "omit_code" in bundle.request.GET: + del bundle.data["code"] - if 'omit_stylized' in bundle.request.GET: - del bundle.data['stylized'] + if "omit_stylized" in bundle.request.GET: + del bundle.data["stylized"] return bundle @@ -274,14 +289,14 @@ class PublicSniptResource(ModelResource): orm_filters = super(PublicSniptResource, self).build_filters(filters) - if 'tag' in filters: - tag = Tag.objects.get(pk=filters['tag']) + if "tag" in filters: + tag = Tag.objects.get(pk=filters["tag"]) tagged_items = tag.taggit_taggeditem_items.all() - orm_filters['pk__in'] = [i.object_id for i in tagged_items] + orm_filters["pk__in"] = [i.object_id for i in tagged_items] - if 'q' in filters: - sqs = SearchQuerySet().auto_query(filters['q']) - orm_filters['pk__in'] = [i.pk for i in sqs] + if "q" in filters: + sqs = SearchQuerySet().auto_query(filters["q"]) + orm_filters["pk__in"] = [i.pk for i in sqs] return orm_filters @@ -289,11 +304,11 @@ class PublicSniptResource(ModelResource): class PrivateUserProfileResource(ModelResource): class Meta: queryset = UserProfile.objects.all() - resource_name = 'profile' - excludes = ['is_pro'] + resource_name = "profile" + excludes = ["is_pro"] validation = UserProfileValidation() include_absolute_url = False - allowed_methods = ['get', 'put'] + allowed_methods = ["get", "put"] list_allowed_methods = [] authentication = ApiKeyAuthentication() authorization = PrivateUserProfileAuthorization() @@ -301,23 +316,22 @@ class PrivateUserProfileResource(ModelResource): max_limit = 200 def dehydrate(self, bundle): - bundle.data['email'] = bundle.obj.user.email - bundle.data['username'] = bundle.obj.user.username - bundle.data['user_id'] = bundle.obj.user.id - bundle.data['api_key'] = bundle.obj.user.api_key.key + bundle.data["email"] = bundle.obj.user.email + bundle.data["username"] = bundle.obj.user.username + bundle.data["user_id"] = bundle.obj.user.id + bundle.data["api_key"] = bundle.obj.user.api_key.key return bundle class PrivateUserResource(ModelResource): - profile = fields.ForeignKey(PrivateUserProfileResource, 'profile', - full=False) + profile = fields.ForeignKey(PrivateUserProfileResource, "profile", full=False) class Meta: queryset = User.objects.all() - resource_name = 'user' - fields = ['id', 'username', 'email'] + resource_name = "user" + fields = ["id", "username", "email"] include_absolute_url = True - allowed_methods = ['get'] + allowed_methods = ["get"] list_allowed_methods = [] authentication = ApiKeyAuthentication() authorization = PrivateUserAuthorization() @@ -326,155 +340,172 @@ class PrivateUserResource(ModelResource): cache = SimpleCache() def dehydrate(self, bundle): - bundle.data['email_md5'] = hashlib \ - .md5(bundle.obj.email.lower().encode('utf-8')) \ - .hexdigest() - bundle.data['stats'] = { - 'public_snipts': Snipt.objects.filter(user=bundle.obj.id, - public=True).count(), - 'private_snipts': Snipt.objects.filter(user=bundle.obj.id, - public=False).count(), - 'total_snipts': Snipt.objects.filter(user=bundle.obj.id).count(), - 'total_views': Snipt.objects.filter(user=bundle.obj.id).aggregate( - models.Sum('views'))['views__sum'] + bundle.data["email_md5"] = hashlib.md5( + bundle.obj.email.lower().encode("utf-8") + ).hexdigest() + bundle.data["stats"] = { + "public_snipts": Snipt.objects.filter( + user=bundle.obj.id, public=True + ).count(), + "private_snipts": Snipt.objects.filter( + user=bundle.obj.id, public=False + ).count(), + "total_snipts": Snipt.objects.filter(user=bundle.obj.id).count(), + "total_views": Snipt.objects.filter(user=bundle.obj.id).aggregate( + models.Sum("views") + )["views__sum"], } user_snipts = Snipt.objects.filter(user=bundle.obj) - user_tags = [ - snipt['tags'] for snipt in user_snipts.values('tags').distinct() - ] + user_tags = [snipt["tags"] for snipt in user_snipts.values("tags").distinct()] tags = [ - tag['name'] for tag in - Tag.objects.filter(id__in=user_tags).values('name').distinct() + tag["name"] + for tag in Tag.objects.filter(id__in=user_tags).values("name").distinct() ] - bundle.data['tags'] = tags + bundle.data["tags"] = tags - bundle.data['lexers'] = [ - snipt['lexer'] for snipt in user_snipts - .values('lexer').distinct()] + bundle.data["lexers"] = [ + snipt["lexer"] for snipt in user_snipts.values("lexer").distinct() + ] return bundle class PrivateSniptResource(ModelResource): - user = fields.ForeignKey(PrivateUserResource, 'user', full=True) - last_user_saved = fields.ForeignKey(PrivateUserResource, - 'last_user_saved', - null=True, - full=False) + user = fields.ForeignKey(PrivateUserResource, "user", full=True) + last_user_saved = fields.ForeignKey( + PrivateUserResource, "last_user_saved", null=True, full=False + ) tags_list = ListField() - tags = fields.ToManyField(PublicTagResource, 'tags', related_name='tag', - full=True) + tags = fields.ToManyField(PublicTagResource, "tags", related_name="tag", full=True) class Meta: - queryset = Snipt.objects.all().order_by('-created') - resource_name = 'snipt' - fields = ['id', 'title', 'slug', 'lexer', 'code', 'description', - 'line_count', 'stylized', 'key', 'public', 'secure', - 'blog_post', 'created', 'modified', 'publish_date', 'meta'] + queryset = Snipt.objects.all().order_by("-created") + resource_name = "snipt" + fields = [ + "id", + "title", + "slug", + "lexer", + "code", + "description", + "line_count", + "stylized", + "key", + "public", + "secure", + "blog_post", + "created", + "modified", + "publish_date", + "meta", + ] include_absolute_url = True - detail_allowed_methods = ['get', 'patch', 'put', 'delete'] - list_allowed_methods = ['get', 'post'] + detail_allowed_methods = ["get", "patch", "put", "delete"] + list_allowed_methods = ["get", "post"] authentication = ApiKeyAuthentication() authorization = PrivateSniptAuthorization() validation = SniptValidation() - ordering = ['created', 'modified'] + ordering = ["created", "modified"] always_return_data = True max_limit = 200 cache = SimpleCache() def dehydrate(self, bundle): - bundle.data['embed_url'] = bundle.obj.get_embed_url() - bundle.data['raw_url'] = bundle.obj.get_raw_url() - bundle.data['tags_list'] = edit_string_for_tags(bundle.obj.tags.all()) - bundle.data['full_absolute_url'] = bundle.obj.get_full_absolute_url() - bundle.data['description_rendered'] = \ - linebreaksbr(urlize(bundle.obj.description)) - bundle.data['views'] = bundle.obj.views - bundle.data['favs'] = bundle.obj.favs() + bundle.data["embed_url"] = bundle.obj.get_embed_url() + bundle.data["raw_url"] = bundle.obj.get_raw_url() + bundle.data["tags_list"] = edit_string_for_tags(bundle.obj.tags.all()) + bundle.data["full_absolute_url"] = bundle.obj.get_full_absolute_url() + bundle.data["description_rendered"] = linebreaksbr( + urlize(bundle.obj.description) + ) + bundle.data["views"] = bundle.obj.views + bundle.data["favs"] = bundle.obj.favs() - if bundle.data['publish_date']: - bundle.data['publish_date'] = \ - date(bundle.data['publish_date'], 'M d, Y \\a\\t h:i A') + if bundle.data["publish_date"]: + bundle.data["publish_date"] = date( + bundle.data["publish_date"], "M d, Y \\a\\t h:i A" + ) log_entries = bundle.obj.sniptlogentry_set.all() bundle_log_entries = [] for entry in log_entries: - bundle_log_entries.append({ - 'created': entry.created, - 'user': entry.user, - 'code': entry.code, - 'diff': entry.diff - }) + bundle_log_entries.append( + { + "created": entry.created, + "user": entry.user, + "code": entry.code, + "diff": entry.diff, + } + ) - bundle.data['log_entries'] = bundle_log_entries + bundle.data["log_entries"] = bundle_log_entries return bundle def obj_create(self, bundle, **kwargs): - bundle.data['last_user_saved'] = bundle.request.user - bundle.data['tags_list'] = bundle.data.get('tags') - bundle.data['tags'] = [] + bundle.data["last_user_saved"] = bundle.request.user + bundle.data["tags_list"] = bundle.data.get("tags") + bundle.data["tags"] = [] - if 'intended_user' in bundle.data: - bundle.data['user'] = \ - User.objects.get(username=bundle.data['intended_user']) + if "intended_user" in bundle.data: + bundle.data["user"] = User.objects.get( + username=bundle.data["intended_user"] + ) else: - bundle.data['user'] = bundle.request.user + bundle.data["user"] = bundle.request.user - if 'blog_post' in bundle.data: + if "blog_post" in bundle.data: bundle = self._clean_publish_date(bundle) - return super(PrivateSniptResource, self) \ - .obj_create(bundle, **kwargs) + return super(PrivateSniptResource, self).obj_create(bundle, **kwargs) def obj_update(self, bundle, **kwargs): - instance = Snipt.objects.get(pk=bundle.data['id']) + instance = Snipt.objects.get(pk=bundle.data["id"]) - if (instance.user.profile.is_a_team): + if instance.user.profile.is_a_team: user = instance.user else: user = bundle.request.user - bundle.data['created'] = None - bundle.data['last_user_saved'] = bundle.request.user - bundle.data['modified'] = None - bundle.data['user'] = user + bundle.data["created"] = None + bundle.data["last_user_saved"] = bundle.request.user + bundle.data["modified"] = None + bundle.data["user"] = user - if type(bundle.data['tags']) == str or type(bundle.data['tags']) == unicode: - bundle.data['tags_list'] = bundle.data['tags'] + if type(bundle.data["tags"]) == str or type(bundle.data["tags"]) == unicode: + bundle.data["tags_list"] = bundle.data["tags"] else: - bundle.data['tags_list'] = '' - bundle.data['tags'] = '' + bundle.data["tags_list"] = "" + bundle.data["tags"] = "" - if 'blog_post' in bundle.data: + if "blog_post" in bundle.data: bundle = self._clean_publish_date(bundle) - return super(PrivateSniptResource, self) \ - .obj_update(bundle, **kwargs) + return super(PrivateSniptResource, self).obj_update(bundle, **kwargs) def _clean_publish_date(self, bundle): - if bundle.data['blog_post'] and 'publish_date' not in bundle.data: - bundle.data['publish_date'] = datetime.datetime.now() - elif bundle.data['publish_date'] == '': - bundle.data['publish_date'] = datetime.datetime.now() - elif bundle.data['blog_post']: + if bundle.data["blog_post"] and "publish_date" not in bundle.data: + bundle.data["publish_date"] = datetime.datetime.now() + elif bundle.data["publish_date"] == "": + bundle.data["publish_date"] = datetime.datetime.now() + elif bundle.data["blog_post"]: c = pdt.Constants() p = pdt.Calendar(c) - publish_date, result = p.parse(bundle.data['publish_date']) + publish_date, result = p.parse(bundle.data["publish_date"]) if result != 0: - publish_date = time.strftime('%Y-%m-%d %H:%M:%S', publish_date) + publish_date = time.strftime("%Y-%m-%d %H:%M:%S", publish_date) else: publish_date = datetime.datetime.now() - bundle.data['publish_date'] = publish_date - elif not bundle.data['blog_post']: - bundle.data['publish_date'] = None + bundle.data["publish_date"] = publish_date + elif not bundle.data["blog_post"]: + bundle.data["publish_date"] = None return bundle @@ -484,51 +515,51 @@ class PrivateSniptResource(ModelResource): orm_filters = super(PrivateSniptResource, self).build_filters(filters) - if 'tag' in filters: - tag = Tag.objects.get(pk=filters['tag']) + if "tag" in filters: + tag = Tag.objects.get(pk=filters["tag"]) tagged_items = tag.taggit_taggeditem_items.all() - orm_filters['pk__in'] = [i.object_id for i in tagged_items] + orm_filters["pk__in"] = [i.object_id for i in tagged_items] - if 'q' in filters: - user = User.objects.get(username=filters['username']) - sqs = SearchQuerySet().filter(author=user, content=filters['q']) - orm_filters['pk__in'] = [i.pk for i in sqs] + if "q" in filters: + user = User.objects.get(username=filters["username"]) + sqs = SearchQuerySet().filter(author=user, content=filters["q"]) + orm_filters["pk__in"] = [i.pk for i in sqs] return orm_filters def save_m2m(self, bundle): - tags = bundle.data.get('tags_list', []) - if tags != '': + tags = bundle.data.get("tags_list", []) + if tags != "": bundle.obj.tags.set(*parse_tags(tags)) else: bundle.obj.tags.set() class PrivateFavoriteResource(ModelResource): - user = fields.ForeignKey(PrivateUserResource, 'user', full=True) - snipt = fields.ForeignKey(PrivateSniptResource, 'snipt', full=False) + user = fields.ForeignKey(PrivateUserResource, "user", full=True) + snipt = fields.ForeignKey(PrivateSniptResource, "snipt", full=False) class Meta: - queryset = Favorite.objects.all().order_by('-created') - resource_name = 'favorite' - fields = ['id'] + queryset = Favorite.objects.all().order_by("-created") + resource_name = "favorite" + fields = ["id"] validation = FavoriteValidation() - detail_allowed_methods = ['get', 'post', 'delete'] - list_allowed_methods = ['get', 'post'] + detail_allowed_methods = ["get", "post", "delete"] + list_allowed_methods = ["get", "post"] authentication = ApiKeyAuthentication() authorization = PrivateFavoriteAuthorization() - ordering = ['created'] + ordering = ["created"] always_return_data = True max_limit = 200 cache = SimpleCache() def dehydrate(self, bundle): - bundle.data['snipt'] = '/api/public/snipt/{}/'.format( - bundle.obj.snipt.pk) + bundle.data["snipt"] = "/api/public/snipt/{}/".format(bundle.obj.snipt.pk) return bundle def obj_create(self, bundle, **kwargs): - bundle.data['user'] = bundle.request.user - bundle.data['snipt'] = Snipt.objects.get(pk=bundle.data['snipt']) - return super(PrivateFavoriteResource, self) \ - .obj_create(bundle, user=bundle.request.user, **kwargs) + bundle.data["user"] = bundle.request.user + bundle.data["snipt"] = Snipt.objects.get(pk=bundle.data["snipt"]) + return super(PrivateFavoriteResource, self).obj_create( + bundle, user=bundle.request.user, **kwargs + ) diff --git a/snipts/management/commands/import_snipts.py b/snipts/management/commands/import_snipts.py index 3511140..03120b3 100644 --- a/snipts/management/commands/import_snipts.py +++ b/snipts/management/commands/import_snipts.py @@ -8,15 +8,22 @@ import requests def get_snipts(api_key, from_username, url=None, snipts=[]): - path = url or '/api/private/snipt/?limit=50&api_key={}&username={}&format=json'.format(api_key, from_username) - res = requests.get('https://snippets.siftie.com' + path) + path = ( + url + or "/api/private/snipt/?limit=50&api_key={}&username={}&format=json".format( + api_key, from_username + ) + ) + res = requests.get("https://snippets.siftie.com" + path) json = res.json() - print(u"Fetched snipts {} through {} of {}".format( - json["meta"]["offset"], - json["meta"]["offset"] + json["meta"]["limit"], - json["meta"]["total_count"] - )) + print( + u"Fetched snipts {} through {} of {}".format( + json["meta"]["offset"], + json["meta"]["offset"] + json["meta"]["limit"], + json["meta"]["total_count"], + ) + ) snipts.extend(json["objects"]) @@ -30,14 +37,14 @@ class Command(BaseCommand): help = u"Import snipts from Siftie Snippets." def add_arguments(self, parser): - parser.add_argument('api_key', nargs='+', type=str) - parser.add_argument('from_username', nargs='+', type=str) - parser.add_argument('to_username', nargs='+', type=str) + parser.add_argument("api_key", nargs="+", type=str) + parser.add_argument("from_username", nargs="+", type=str) + parser.add_argument("to_username", nargs="+", type=str) def handle(self, *args, **options): - api_key = options['api_key'][0] - from_username = options['from_username'][0] - to_username = options['to_username'][0] + api_key = options["api_key"][0] + from_username = options["from_username"][0] + to_username = options["to_username"][0] to_user = User.objects.get(username=to_username) print(u"Fetching snipts...") @@ -62,7 +69,7 @@ class Command(BaseCommand): stylized=snipt["stylized"], title=snipt["title"], user=to_user, - views=snipt["views"] + views=snipt["views"], ) s.created = snipt["created"] diff --git a/snipts/migrations/0001_initial.py b/snipts/migrations/0001_initial.py index 8f428e8..d48fd83 100644 --- a/snipts/migrations/0001_initial.py +++ b/snipts/migrations/0001_initial.py @@ -9,53 +9,90 @@ import taggit.managers class Migration(migrations.Migration): dependencies = [ - ('taggit', '0001_initial'), + ("taggit", "0001_initial"), migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ migrations.CreateModel( - name='Favorite', + name="Favorite", fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('created', models.DateTimeField(auto_now_add=True)), - ('modified', models.DateTimeField(auto_now=True)), + ( + "id", + models.AutoField( + verbose_name="ID", + serialize=False, + auto_created=True, + primary_key=True, + ), + ), + ("created", models.DateTimeField(auto_now_add=True)), + ("modified", models.DateTimeField(auto_now=True)), ], ), migrations.CreateModel( - name='Snipt', + name="Snipt", fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('title', models.CharField(default=b'Untitled', max_length=255, null=True, blank=True)), - ('slug', models.SlugField(max_length=255, blank=True)), - ('custom_slug', models.SlugField(max_length=255, blank=True)), - ('lexer', models.CharField(max_length=50)), - ('code', models.TextField()), - ('meta', models.TextField(null=True, blank=True)), - ('description', models.TextField(null=True, blank=True)), - ('stylized', models.TextField(null=True, blank=True)), - ('stylized_min', models.TextField(null=True, blank=True)), - ('embedded', models.TextField(null=True, blank=True)), - ('line_count', models.IntegerField(default=None, null=True, blank=True)), - ('key', models.CharField(max_length=100, null=True, blank=True)), - ('public', models.BooleanField(default=False)), - ('blog_post', models.BooleanField(default=False)), - ('views', models.IntegerField(default=0)), - ('created', models.DateTimeField(auto_now_add=True)), - ('modified', models.DateTimeField(auto_now=True)), - ('publish_date', models.DateTimeField(null=True, blank=True)), - ('tags', taggit.managers.TaggableManager(to='taggit.Tag', through='taggit.TaggedItem', help_text='A comma-separated list of tags.', verbose_name='Tags')), - ('user', models.ForeignKey(blank=True, to=settings.AUTH_USER_MODEL, null=True)), + ( + "id", + models.AutoField( + verbose_name="ID", + serialize=False, + auto_created=True, + primary_key=True, + ), + ), + ( + "title", + models.CharField( + default=b"Untitled", max_length=255, null=True, blank=True + ), + ), + ("slug", models.SlugField(max_length=255, blank=True)), + ("custom_slug", models.SlugField(max_length=255, blank=True)), + ("lexer", models.CharField(max_length=50)), + ("code", models.TextField()), + ("meta", models.TextField(null=True, blank=True)), + ("description", models.TextField(null=True, blank=True)), + ("stylized", models.TextField(null=True, blank=True)), + ("stylized_min", models.TextField(null=True, blank=True)), + ("embedded", models.TextField(null=True, blank=True)), + ( + "line_count", + models.IntegerField(default=None, null=True, blank=True), + ), + ("key", models.CharField(max_length=100, null=True, blank=True)), + ("public", models.BooleanField(default=False)), + ("blog_post", models.BooleanField(default=False)), + ("views", models.IntegerField(default=0)), + ("created", models.DateTimeField(auto_now_add=True)), + ("modified", models.DateTimeField(auto_now=True)), + ("publish_date", models.DateTimeField(null=True, blank=True)), + ( + "tags", + taggit.managers.TaggableManager( + to="taggit.Tag", + through="taggit.TaggedItem", + help_text="A comma-separated list of tags.", + verbose_name="Tags", + ), + ), + ( + "user", + models.ForeignKey( + blank=True, to=settings.AUTH_USER_MODEL, null=True + ), + ), ], ), migrations.AddField( - model_name='favorite', - name='snipt', - field=models.ForeignKey(to='snipts.Snipt'), + model_name="favorite", + name="snipt", + field=models.ForeignKey(to="snipts.Snipt"), ), migrations.AddField( - model_name='favorite', - name='user', + model_name="favorite", + name="user", field=models.ForeignKey(to=settings.AUTH_USER_MODEL), ), ] diff --git a/snipts/migrations/0002_sniptlogentry.py b/snipts/migrations/0002_sniptlogentry.py index 5557190..24b9fb7 100644 --- a/snipts/migrations/0002_sniptlogentry.py +++ b/snipts/migrations/0002_sniptlogentry.py @@ -9,20 +9,28 @@ class Migration(migrations.Migration): dependencies = [ migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('snipts', '0001_initial'), + ("snipts", "0001_initial"), ] operations = [ migrations.CreateModel( - name='SniptLogEntry', + name="SniptLogEntry", fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('code', models.TextField()), - ('diff', models.TextField()), - ('created', models.DateTimeField(auto_now_add=True)), - ('modified', models.DateTimeField(auto_now=True)), - ('snipt', models.ForeignKey(to='snipts.Snipt')), - ('user', models.ForeignKey(to=settings.AUTH_USER_MODEL)), + ( + "id", + models.AutoField( + verbose_name="ID", + serialize=False, + auto_created=True, + primary_key=True, + ), + ), + ("code", models.TextField()), + ("diff", models.TextField()), + ("created", models.DateTimeField(auto_now_add=True)), + ("modified", models.DateTimeField(auto_now=True)), + ("snipt", models.ForeignKey(to="snipts.Snipt")), + ("user", models.ForeignKey(to=settings.AUTH_USER_MODEL)), ], - ), + ) ] diff --git a/snipts/migrations/0003_snipt_last_user_saved.py b/snipts/migrations/0003_snipt_last_user_saved.py index 56200e9..ead53ca 100644 --- a/snipts/migrations/0003_snipt_last_user_saved.py +++ b/snipts/migrations/0003_snipt_last_user_saved.py @@ -9,13 +9,18 @@ class Migration(migrations.Migration): dependencies = [ migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('snipts', '0002_sniptlogentry'), + ("snipts", "0002_sniptlogentry"), ] operations = [ migrations.AddField( - model_name='snipt', - name='last_user_saved', - field=models.ForeignKey(related_name='last_user_saved', blank=True, to=settings.AUTH_USER_MODEL, null=True), - ), + model_name="snipt", + name="last_user_saved", + field=models.ForeignKey( + related_name="last_user_saved", + blank=True, + to=settings.AUTH_USER_MODEL, + null=True, + ), + ) ] diff --git a/snipts/migrations/0004_auto_20160512_1058.py b/snipts/migrations/0004_auto_20160512_1058.py index bee493a..0f6890a 100644 --- a/snipts/migrations/0004_auto_20160512_1058.py +++ b/snipts/migrations/0004_auto_20160512_1058.py @@ -6,19 +6,17 @@ from django.db import models, migrations class Migration(migrations.Migration): - dependencies = [ - ('snipts', '0003_snipt_last_user_saved'), - ] + dependencies = [("snipts", "0003_snipt_last_user_saved")] operations = [ migrations.AddField( - model_name='snipt', - name='secure', - field=models.BooleanField(default=False), + model_name="snipt", name="secure", field=models.BooleanField(default=False) ), migrations.AlterField( - model_name='snipt', - name='title', - field=models.CharField(max_length=255, blank=True, null=True, default='Untitled'), + model_name="snipt", + name="title", + field=models.CharField( + max_length=255, blank=True, null=True, default="Untitled" + ), ), ] diff --git a/snipts/migrations/0005_sniptsecureview.py b/snipts/migrations/0005_sniptsecureview.py index 62a7274..655438d 100644 --- a/snipts/migrations/0005_sniptsecureview.py +++ b/snipts/migrations/0005_sniptsecureview.py @@ -9,18 +9,26 @@ class Migration(migrations.Migration): dependencies = [ migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('snipts', '0004_auto_20160512_1058'), + ("snipts", "0004_auto_20160512_1058"), ] operations = [ migrations.CreateModel( - name='SniptSecureView', + name="SniptSecureView", fields=[ - ('id', models.AutoField(serialize=False, primary_key=True, auto_created=True, verbose_name='ID')), - ('created', models.DateTimeField(auto_now_add=True)), - ('modified', models.DateTimeField(auto_now=True)), - ('snipt', models.ForeignKey(to='snipts.Snipt')), - ('user', models.ForeignKey(to=settings.AUTH_USER_MODEL)), + ( + "id", + models.AutoField( + serialize=False, + primary_key=True, + auto_created=True, + verbose_name="ID", + ), + ), + ("created", models.DateTimeField(auto_now_add=True)), + ("modified", models.DateTimeField(auto_now=True)), + ("snipt", models.ForeignKey(to="snipts.Snipt")), + ("user", models.ForeignKey(to=settings.AUTH_USER_MODEL)), ], - ), + ) ] diff --git a/snipts/models.py b/snipts/models.py index 3abcde4..0e88610 100644 --- a/snipts/models.py +++ b/snipts/models.py @@ -23,14 +23,15 @@ class Snipt(models.Model): """An individual Snipt.""" user = models.ForeignKey(User, blank=True, null=True, on_delete=models.DO_NOTHING) - last_user_saved = models.ForeignKey(User, - blank=True, - null=True, - related_name='last_user_saved', - on_delete=models.DO_NOTHING) + last_user_saved = models.ForeignKey( + User, + blank=True, + null=True, + related_name="last_user_saved", + on_delete=models.DO_NOTHING, + ) - title = models.CharField(max_length=255, blank=True, null=True, - default='Untitled') + title = models.CharField(max_length=255, blank=True, null=True, default="Untitled") slug = models.SlugField(max_length=255, blank=True) custom_slug = models.SlugField(max_length=255, blank=True) tags = TaggableManager() @@ -61,7 +62,7 @@ class Snipt(models.Model): diff = difflib.unified_diff(expected, actual) - return ''.join(diff) + return "".join(diff) def __init__(self, *args, **kwargs): super(Snipt, self).__init__(*args, **kwargs) @@ -73,92 +74,101 @@ class Snipt(models.Model): self.slug = slugify_uniquely(self.title, Snipt) if not self.key: - self.key = hashlib.md5((self.slug + - str(datetime.datetime.now()) + - str(random.random())).encode('utf-8')).hexdigest() + self.key = hashlib.md5( + ( + self.slug + str(datetime.datetime.now()) + str(random.random()) + ).encode("utf-8") + ).hexdigest() - if self.lexer == 'markdown': - self.stylized = markdown(self.code, 'default') + if self.lexer == "markdown": + self.stylized = markdown(self.code, "default") # Snippet embeds - for match in re.findall('\[\[(\w{32})\]\]', self.stylized): - self.stylized = self.stylized.replace('[[' + str(match) + ']]', - """ + for match in re.findall("\[\[(\w{32})\]\]", self.stylized): + self.stylized = self.stylized.replace( + "[[" + str(match) + "]]", + """ -
""".format(match, match)) +
""".format( + match, match + ), + ) # YouTube embeds - for match in re.findall('\[\[youtube-(\w{11})\-(\d+)x(\d+)\]\]', - self.stylized): - self.stylized = self.stylized \ - .replace('[[youtube-{}-{}x{}]]'.format( - str(match[0]), - str(match[1]), - str(match[2])), - """""" - .format(match[1], match[2], match[0])) + frameborder="0" allowfullscreen>""".format( + match[1], match[2], match[0] + ), + ) # Vimeo embeds - for match in re.findall('\[\[vimeo-(\d+)\-(\d+)x(\d+)\]\]', - self.stylized): - self.stylized = self.stylized \ - .replace('[[vimeo-{}-{}x{}]]'.format( - str(match[0]), - str(match[1]), - str(match[2])), - """""" - .format(match[0], match[1], match[2])) + allowFullScreen>""".format( + match[0], match[1], match[2] + ), + ) # Tweet embeds - for match in re.findall('\[\[tweet-(\d+)\]\]', self.stylized): - self.stylized = self.stylized \ - .replace( - '[[tweet-{}]]'.format(str(match)), - '
' - .format(str(match))) + for match in re.findall("\[\[tweet-(\d+)\]\]", self.stylized): + self.stylized = self.stylized.replace( + "[[tweet-{}]]".format(str(match)), + '
'.format( + str(match) + ), + ) # Parse usernames - for match in re.findall('@(\w+) ', self.stylized): + for match in re.findall("@(\w+) ", self.stylized): # Try and get the user by username. user = get_object_or_None(User, username=match) if user: url = user.profile.get_user_profile_url() - self.stylized = self.stylized \ - .replace('@{} '.format(str(match)), - '@{} '.format(url, match)) + self.stylized = self.stylized.replace( + "@{} ".format(str(match)), + '@{} '.format(url, match), + ) else: - self.stylized = highlight(self.code, - get_lexer_by_name(self.lexer, - encoding='UTF-8'), - HtmlFormatter(linenos='table', - anchorlinenos=True, - lineanchors='L', - linespans='L', - )) - self.line_count = len(self.code.split('\n')) + self.stylized = highlight( + self.code, + get_lexer_by_name(self.lexer, encoding="UTF-8"), + HtmlFormatter( + linenos="table", anchorlinenos=True, lineanchors="L", linespans="L" + ), + ) + self.line_count = len(self.code.split("\n")) - if self.lexer == 'markdown': - lexer_for_embedded = 'text' + if self.lexer == "markdown": + lexer_for_embedded = "text" else: lexer_for_embedded = self.lexer - embedded = highlight(self.code, - get_lexer_by_name(lexer_for_embedded, - encoding='UTF-8'), - HtmlFormatter( - style='native', - noclasses=True, - prestyles=""" + embedded = highlight( + self.code, + get_lexer_by_name(lexer_for_embedded, encoding="UTF-8"), + HtmlFormatter( + style="native", + noclasses=True, + prestyles=""" background-color: #1C1C1C; border-radius: 5px; color: #D0D0D0; @@ -169,22 +179,25 @@ class Snipt(models.Model): padding: 15px; -webkit-border-radius: 5px; -moz-border-radius: 5px; - """)) - embedded = (embedded.replace("\\\"", "\\\\\"") - .replace('\'', '\\\'') - .replace("\\", "\\\\") - .replace('background: #202020', '')) + """, + ), + ) + embedded = ( + embedded.replace('\\"', '\\\\"') + .replace("'", "\\'") + .replace("\\", "\\\\") + .replace("background: #202020", "") + ) self.embedded = embedded snipt = super(Snipt, self).save(*args, **kwargs) - diff = self._unidiff_output(self.original_code or '', self.code) + diff = self._unidiff_output(self.original_code or "", self.code) - if (diff != ''): - log_entry = SniptLogEntry(user=self.last_user_saved, - snipt=self, - code=self.code, - diff=diff) + if diff != "": + log_entry = SniptLogEntry( + user=self.last_user_saved, snipt=self, code=self.code, diff=diff + ) log_entry.save() return snipt @@ -197,52 +210,52 @@ class Snipt(models.Model): def get_stylized_min(self): if self.stylized_min is None: - if self.lexer == 'markdown': - self.stylized_min = markdown(self.code[:1000], 'default') + if self.lexer == "markdown": + self.stylized_min = markdown(self.code[:1000], "default") else: self.stylized_min = highlight( self.code[:1000], - get_lexer_by_name(self.lexer, encoding='UTF-8'), - HtmlFormatter(linenos='table', - linenospecial=1, - lineanchors='line')) + get_lexer_by_name(self.lexer, encoding="UTF-8"), + HtmlFormatter(linenos="table", linenospecial=1, lineanchors="line"), + ) return self.stylized_min def get_absolute_url(self): if self.blog_post: if self.user.profile.blog_domain: - return u'http://{}/{}/'.format( - self.user.profile.blog_domain.split(' ')[0], self.slug) + return u"http://{}/{}/".format( + self.user.profile.blog_domain.split(" ")[0], self.slug + ) else: - return u'https://{}.snippets.siftie.com/{}/'.format( - self.user.username.replace('_', '-'), self.slug) + return u"https://{}.snippets.siftie.com/{}/".format( + self.user.username.replace("_", "-"), self.slug + ) if self.custom_slug: - return u'/{}/'.format(self.custom_slug) + return u"/{}/".format(self.custom_slug) if self.public: - return u'/{}/{}/'.format(self.user.username, self.slug) + return u"/{}/{}/".format(self.user.username, self.slug) else: - return u'/{}/{}/?key={}'.format( - self.user.username, self.slug, self.key) + return u"/{}/{}/?key={}".format(self.user.username, self.slug, self.key) def get_full_absolute_url(self): if self.blog_post: if self.user.profile.blog_domain: - return u'http://{}/{}/'.format( - self.user.profile.blog_domain.split(' ')[0], self.slug) + return u"http://{}/{}/".format( + self.user.profile.blog_domain.split(" ")[0], self.slug + ) else: - return u'https://{}.snippets.siftie.com/{}/'.format( - self.user.username, self.slug) + return u"https://{}.snippets.siftie.com/{}/".format( + self.user.username, self.slug + ) if self.public: - return u'/{}/{}/'.format(self.user.username, self.slug) + return u"/{}/{}/".format(self.user.username, self.slug) else: - return u'/{}/{}/?key={}'.format(self.user.username, - self.slug, - self.key) + return u"/{}/{}/?key={}".format(self.user.username, self.slug, self.key) def get_download_url(self): @@ -252,30 +265,30 @@ class Snipt(models.Model): lexer_obj = None if lexer_obj and lexer_obj.filenames: - filename = lexer_obj.filenames[0].replace('*', self.slug) + filename = lexer_obj.filenames[0].replace("*", self.slug) else: - if self.lexer == 'markdown': - filename = u'{}.md'.format(self.slug) + if self.lexer == "markdown": + filename = u"{}.md".format(self.slug) else: - filename = u'{}.txt'.format(self.slug) + filename = u"{}.txt".format(self.slug) - return u'/download/{}/{}'.format(self.key, filename) + return u"/download/{}/{}".format(self.key, filename) def get_embed_url(self): if settings.DEBUG: - root = 'http://local.snippets.siftie.com' + root = "http://local.snippets.siftie.com" else: - root = 'https://snippets.siftie.com' + root = "https://snippets.siftie.com" - return '{}/embed/{}/'.format(root, self.key) + return "{}/embed/{}/".format(root, self.key) def get_raw_url(self): - return '/raw/{}/'.format(self.key) + return "/raw/{}/".format(self.key) @property def sorted_tags(self): - return self.tags.all().order_by('name') + return self.tags.all().order_by("name") @property def tags_list(self): @@ -283,8 +296,8 @@ class Snipt(models.Model): @property def lexer_name(self): - if self.lexer == 'markdown': - return 'Markdown' + if self.lexer == "markdown": + return "Markdown" else: return get_lexer_by_name(self.lexer).name @@ -311,7 +324,7 @@ class SniptLogEntry(models.Model): @property def snipt_name(self): - return self.snipt.title or 'Untitled' + return self.snipt.title or "Untitled" class SniptSecureView(models.Model): @@ -325,7 +338,7 @@ class SniptSecureView(models.Model): @property def snipt_name(self): - return self.snipt.title or 'Untitled' + return self.snipt.title or "Untitled" class Favorite(models.Model): @@ -336,5 +349,4 @@ class Favorite(models.Model): modified = models.DateTimeField(auto_now=True, editable=False) def __unicode__(self): - return u'{} favorited by {}'.format(self.snipt.title, - self.user.username) + return u"{} favorited by {}".format(self.snipt.title, self.user.username) diff --git a/snipts/search_indexes.py b/snipts/search_indexes.py index 0573891..a5a1cf0 100644 --- a/snipts/search_indexes.py +++ b/snipts/search_indexes.py @@ -6,15 +6,14 @@ from snipts.models import Snipt class SniptIndex(indexes.SearchIndex, indexes.Indexable): text = indexes.CharField(document=True, use_template=True) - author = indexes.CharField(model_attr='user') - pub_date = indexes.DateTimeField(model_attr='created') - public = indexes.BooleanField(model_attr='public') - typ = indexes.CharField(model_attr='lexer') + author = indexes.CharField(model_attr="user") + pub_date = indexes.DateTimeField(model_attr="created") + public = indexes.BooleanField(model_attr="public") + typ = indexes.CharField(model_attr="lexer") def get_model(self): return Snipt def index_queryset(self, **kwargs): """Used when the entire index for model is updated.""" - return self.get_model().objects.filter( - created__lte=datetime.datetime.now()) + return self.get_model().objects.filter(created__lte=datetime.datetime.now()) diff --git a/snipts/templatetags/snipt_tags.py b/snipts/templatetags/snipt_tags.py index d48a839..cf57e6b 100644 --- a/snipts/templatetags/snipt_tags.py +++ b/snipts/templatetags/snipt_tags.py @@ -10,11 +10,11 @@ from templatetag_sugar.register import tag register = template.Library() -@tag(register, [Constant('as'), Variable()]) +@tag(register, [Constant("as"), Variable()]) def snipt_is_favorited_by_user(context, asvar): - user = context['request'].user - snipt = context['snipt'] + user = context["request"].user + snipt = context["snipt"] is_favorited = False @@ -27,37 +27,37 @@ def snipt_is_favorited_by_user(context, asvar): context[asvar] = is_favorited - return '' + return "" @tag(register, []) def snipts_count_for_user(context): - user = context['request'].user + user = context["request"].user if user.is_authenticated(): - snipts = Snipt.objects.filter(user=user).values('id').count() + snipts = Snipt.objects.filter(user=user).values("id").count() else: snipts = 0 return snipts -@tag(register, [Constant('as'), Variable()]) +@tag(register, [Constant("as"), Variable()]) def signup_enabled(context, asvar): context[asvar] = os.environ.get("DISABLE_SIGNUP") != "true" - return '' + return "" -@tag(register, [Constant('as'), Variable()]) +@tag(register, [Constant("as"), Variable()]) def get_lexers(context, asvar): context[asvar] = get_lexers_list() - return '' + return "" -@tag(register, [Constant('for'), Variable()]) +@tag(register, [Constant("for"), Variable()]) def generate_line_numbers(context, line_numbers): - html = '' + html = "" for i in range(1, line_numbers + 1): html = html + '{}'.format(i) @@ -67,7 +67,7 @@ def generate_line_numbers(context, line_numbers): @register.filter def md5(string): - return hashlib.md5(string.lower().encode('utf-8')).hexdigest() + return hashlib.md5(string.lower().encode("utf-8")).hexdigest() @register.filter diff --git a/snipts/tests.py b/snipts/tests.py index 87af1b2..b13e7eb 100644 --- a/snipts/tests.py +++ b/snipts/tests.py @@ -5,107 +5,113 @@ from tastypie.test import ResourceTestCase class SniptResourceTest(ResourceTestCase): - fixtures = ['test_entries.json'] + fixtures = ["test_entries.json"] def setUp(self): super(SniptResourceTest, self).setUp() # Johnny - self.johnny = User.objects.create_user('johnny', 'johnny@siftie.com', - 'password') + self.johnny = User.objects.create_user( + "johnny", "johnny@siftie.com", "password" + ) ApiKey.objects.get_or_create(user=self.johnny) - self.johnny_auth = self.create_apikey(self.johnny, - self.johnny.api_key.key) - self.johnny_private = Snipt(title='Private snippet for Johnny', - lexer='text', - public=False, - user=self.johnny) - self.johnny_public = Snipt(title='Public snippet for Johnny', - lexer='text', - public=True, - user=self.johnny) + self.johnny_auth = self.create_apikey(self.johnny, self.johnny.api_key.key) + self.johnny_private = Snipt( + title="Private snippet for Johnny", + lexer="text", + public=False, + user=self.johnny, + ) + self.johnny_public = Snipt( + title="Public snippet for Johnny", + lexer="text", + public=True, + user=self.johnny, + ) self.johnny_private.save() self.johnny_public.save() # Bob - self.bob = User.objects.create_user('bob', 'bob@siftie.com', 'password') + self.bob = User.objects.create_user("bob", "bob@siftie.com", "password") ApiKey.objects.get_or_create(user=self.bob) self.bob_auth = self.create_apikey(self.bob, self.bob.api_key.key) - self.bob_private = Snipt(title='Private snippet for Bob', - lexer='text', - public=False, - user=self.bob) - self.bob_public = Snipt(title='Public snippet for Bob', - lexer='text', - public=True, - user=self.bob) + self.bob_private = Snipt( + title="Private snippet for Bob", lexer="text", public=False, user=self.bob + ) + self.bob_public = Snipt( + title="Public snippet for Bob", lexer="text", public=True, user=self.bob + ) self.bob_private.save() self.bob_public.save() def test_get_private_list(self): - resp = self.api_client.get('/api/private/snipt/', format='json', - authentication=self.johnny_auth) + resp = self.api_client.get( + "/api/private/snipt/", format="json", authentication=self.johnny_auth + ) self.assertHttpOK(resp) self.assertValidJSONResponse(resp) - self.assertEqual(len(self.deserialize(resp)['objects']), 2) + self.assertEqual(len(self.deserialize(resp)["objects"]), 2) def test_get_private_detail(self): resp = self.api_client.get( - '/api/private/snipt/{}/'.format(self.johnny_private.pk), - format='json', - authentication=self.johnny_auth) + "/api/private/snipt/{}/".format(self.johnny_private.pk), + format="json", + authentication=self.johnny_auth, + ) self.assertHttpOK(resp) self.assertValidJSONResponse(resp) - self.assertEqual(self.deserialize(resp)['key'], - self.johnny_private.key) + self.assertEqual(self.deserialize(resp)["key"], self.johnny_private.key) # Unauthenticated request. resp = self.api_client.get( - '/api/private/snipt/{}/'.format(self.johnny_private.pk), - format='json') + "/api/private/snipt/{}/".format(self.johnny_private.pk), format="json" + ) self.assertHttpUnauthorized(resp) # Unauthorized request. resp = self.api_client.get( - '/api/private/snipt/{}/'.format(self.johnny_private.pk), - format='json', - authentication=self.bob_auth) + "/api/private/snipt/{}/".format(self.johnny_private.pk), + format="json", + authentication=self.bob_auth, + ) self.assertHttpUnauthorized(resp) def test_post_private_list(self): new_snipt = { - 'title': 'A new private snippet.', - 'lexer': 'text', - 'public': False, + "title": "A new private snippet.", + "lexer": "text", + "public": False, } - resp = self.api_client.post('/api/private/snipt/', - data=new_snipt, - format='json', - authentication=self.johnny_auth) + resp = self.api_client.post( + "/api/private/snipt/", + data=new_snipt, + format="json", + authentication=self.johnny_auth, + ) self.assertHttpCreated(resp) self.assertEqual(Snipt.objects.count(), 5) - resp = self.api_client.get('/api/private/snipt/', - format='json', - authentication=self.johnny_auth) - self.assertEqual(len(self.deserialize(resp)['objects']), 3) + resp = self.api_client.get( + "/api/private/snipt/", format="json", authentication=self.johnny_auth + ) + self.assertEqual(len(self.deserialize(resp)["objects"]), 3) - resp = self.api_client.get('/api/public/snipt/', format='json') - self.assertEqual(len(self.deserialize(resp)['objects']), 2) + resp = self.api_client.get("/api/public/snipt/", format="json") + self.assertEqual(len(self.deserialize(resp)["objects"]), 2) def test_get_public_list(self): self.assertEqual(Snipt.objects.count(), 4) - resp = self.api_client.get('/api/public/snipt/', format='json') + resp = self.api_client.get("/api/public/snipt/", format="json") self.assertHttpOK(resp) self.assertValidJSONResponse(resp) - self.assertEqual(len(self.deserialize(resp)['objects']), 2) + self.assertEqual(len(self.deserialize(resp)["objects"]), 2) diff --git a/snipts/urls.py b/snipts/urls.py index 8b512f5..b58d89d 100644 --- a/snipts/urls.py +++ b/snipts/urls.py @@ -3,45 +3,36 @@ from snipts import views urlpatterns = [ - url(r'^s/(?P[^/]+)/(?P[^\?]+)?$', - views.redirect_snipt, name='redirect-snipt'), - url(r'^(?P[^/]+)/feed/$', - views.redirect_user_feed, - name='redirect-feed'), - url(r'^public/tag/(?P[^/]+)/feed/$', + url( + r"^s/(?P[^/]+)/(?P[^\?]+)?$", + views.redirect_snipt, + name="redirect-snipt", + ), + url(r"^(?P[^/]+)/feed/$", views.redirect_user_feed, name="redirect-feed"), + url( + r"^public/tag/(?P[^/]+)/feed/$", views.redirect_public_tag_feed, - name='redirect-public-tag-feed'), - url(r'^(?P[^/]+)/tag/(?P[^/]+)/feed/$', + name="redirect-public-tag-feed", + ), + url( + r"^(?P[^/]+)/tag/(?P[^/]+)/feed/$", views.redirect_user_tag_feed, - name='redirect-user-tag-feed'), - url(r'^public/$', - views.list_public, - name='list-public'), - url(r'^public/tag/(?P[^/]+)/$', - views.list_public, - name='list-public-tag'), - url(r'^download/(?P[^/]+).*$', - views.download, - name='download'), - url(r'^embed/(?P[^/]+)/$', - views.embed, - name='embed'), - url(r'^raw/(?P[^/]+)/(?P[^\?]+)?$', - views.raw, - name='raw'), - url(r'^(?P[^/]+)/$', + name="redirect-user-tag-feed", + ), + url(r"^public/$", views.list_public, name="list-public"), + url( + r"^public/tag/(?P[^/]+)/$", views.list_public, name="list-public-tag" + ), + url(r"^download/(?P[^/]+).*$", views.download, name="download"), + url(r"^embed/(?P[^/]+)/$", views.embed, name="embed"), + url(r"^raw/(?P[^/]+)/(?P[^\?]+)?$", views.raw, name="raw"), + url(r"^(?P[^/]+)/$", views.list_user, name="list-user"), + url( + r"^(?P[^/]+)/tag/(?P[^/]+)/$", views.list_user, - name='list-user'), - url(r'^(?P[^/]+)/tag/(?P[^/]+)/$', - views.list_user, - name='list-user-tag'), - url(r'^(?P[^/]+)/favorites/$', - views.favorites, - name='favorites'), - url(r'^(?P[^/]+)/blog-posts/$', - views.blog_posts, - name='blog-posts'), - url(r'^(?P[^/]+)/(?P[^/]+)/$', - views.detail, - name='detail') - ] + name="list-user-tag", + ), + url(r"^(?P[^/]+)/favorites/$", views.favorites, name="favorites"), + url(r"^(?P[^/]+)/blog-posts/$", views.blog_posts, name="blog-posts"), + url(r"^(?P[^/]+)/(?P[^/]+)/$", views.detail, name="detail"), +] diff --git a/snipts/utils.py b/snipts/utils.py index dc3c062..812e8b2 100644 --- a/snipts/utils.py +++ b/snipts/utils.py @@ -18,12 +18,13 @@ def slugify_uniquely(value, model, slugfield="slug"): potential = str(suffix) if not model.objects.filter(**{slugfield: potential}).count(): return potential - suffix = str(uuid.uuid4()).split('-')[0] + suffix = str(uuid.uuid4()).split("-")[0] def activate_user(user, request, **kwargs): - user = authenticate(username=request.POST['username'], - password=request.POST['password1']) + user = authenticate( + username=request.POST["username"], password=request.POST["password1"] + ) login(request, user) @@ -31,12 +32,13 @@ def get_lexers_list(): lexers = list(get_all_lexers()) for l in lexers: - if l[0] == 'ANTLR With Java Target': + if l[0] == "ANTLR With Java Target": lexers.remove(l) - lexers.append(('Markdown', ('markdown',),)) + lexers.append(("Markdown", ("markdown",))) lexers = sorted(lexers) return lexers + user_registered.connect(activate_user) diff --git a/snipts/views.py b/snipts/views.py index fb653dc..a550cdb 100644 --- a/snipts/views.py +++ b/snipts/views.py @@ -7,7 +7,12 @@ from django.core.mail import send_mail from django.core.paginator import Paginator, InvalidPage from django.db.models import Count from django.db.models import Q -from django.http import Http404, HttpResponse, HttpResponseRedirect, HttpResponseBadRequest +from django.http import ( + Http404, + HttpResponse, + HttpResponseRedirect, + HttpResponseBadRequest, +) from django.shortcuts import get_object_or_404, render from django.template import RequestContext from django.views.decorators.cache import never_cache @@ -21,25 +26,25 @@ from teams.models import Team import os -RESULTS_PER_PAGE = getattr(settings, 'HAYSTACK_SEARCH_RESULTS_PER_PAGE', 20) +RESULTS_PER_PAGE = getattr(settings, "HAYSTACK_SEARCH_RESULTS_PER_PAGE", 20) -@render_to('snipts/detail.html') +@render_to("snipts/detail.html") def detail(request, username, snipt_slug): snipt = get_object_or_404(Snipt, user__username=username, slug=snipt_slug) user = snipt.user - if snipt.lexer != 'markdown': - if 'linenos' not in snipt.stylized: + if snipt.lexer != "markdown": + if "linenos" not in snipt.stylized: snipt.save() if user != request.user: if not snipt.public: - if 'key' not in request.GET: + if "key" not in request.GET: raise Http404 else: - if request.GET.get('key') != snipt.key: + if request.GET.get("key") != snipt.key: raise Http404 if snipt.secure and not request.user.is_authenticated(): @@ -61,35 +66,37 @@ def detail(request, username, snipt_slug): tags = tags.filter(snipt__user=user, snipt__public=True) public = True - tags = tags.annotate(count=Count('taggit_taggeditem_items__id')) - tags = tags.order_by('-count', 'name') + tags = tags.annotate(count=Count("taggit_taggeditem_items__id")) + tags = tags.order_by("-count", "name") return { - 'detail': True, - 'has_snipts': True, - 'public': public, - 'snipt': snipt, - 'tags': tags, - 'user': user, + "detail": True, + "has_snipts": True, + "public": public, + "snipt": snipt, + "tags": tags, + "user": user, } def download(request, snipt_key): snipt = get_object_or_404(Snipt, key=snipt_key) - return HttpResponse(snipt.code, content_type='application/x-download') + return HttpResponse(snipt.code, content_type="application/x-download") def embed(request, snipt_key): snipt = get_object_or_404(Snipt, key=snipt_key) - lines = snipt.embedded.split('\n') - return render(request, - 'snipts/embed.html', - {'lines': lines, 'snipt': snipt}, - content_type='application/javascript') + lines = snipt.embedded.split("\n") + return render( + request, + "snipts/embed.html", + {"lines": lines, "snipt": snipt}, + content_type="application/javascript", + ) -@render_to('snipts/list-user.html') +@render_to("snipts/list-user.html") def blog_posts(request, username): if request.blog_user: @@ -106,29 +113,28 @@ def blog_posts(request, username): public_user = True user = get_object_or_404(User, username=username) snipts = Snipt.objects.filter(blog_post=True, user=user, public=True) - tags = Tag.objects.filter(snipt__user=user, - snipt__public=True).distinct() + tags = Tag.objects.filter(snipt__user=user, snipt__public=True).distinct() - tags = tags.order_by('name') - snipts = snipts.order_by('-created') + tags = tags.order_by("name") + snipts = snipts.order_by("-created") context = { - 'has_snipts': True, - 'public': public, - 'public_user': public_user, - 'snipts': snipts, - 'tags': tags, - 'user': user, + "has_snipts": True, + "public": public, + "public_user": public_user, + "snipts": snipts, + "tags": tags, + "user": user, } - if 'rss' in request.GET: - context['snipts'] = context['snipts'][:20] + if "rss" in request.GET: + context["snipts"] = context["snipts"][:20] return rss(request, context) return context -@render_to('snipts/list-user.html') +@render_to("snipts/list-user.html") def favorites(request, username): if request.user.username != username: @@ -139,39 +145,39 @@ def favorites(request, username): public = False - favorites = Favorite.objects.filter(user=request.user).values('snipt') - favorites = [f['snipt'] for f in favorites] + favorites = Favorite.objects.filter(user=request.user).values("snipt") + favorites = [f["snipt"] for f in favorites] snipts = Snipt.objects.filter(Q(pk__in=favorites)) tags = Tag.objects.filter(snipt__user=request.user).distinct() - tags = tags.order_by('name') - snipts = snipts.order_by('-created') + tags = tags.order_by("name") + snipts = snipts.order_by("-created") context = { - 'favorites': favorites, - 'has_snipts': True, - 'public': public, - 'public_user': False, - 'snipts': snipts, - 'tags': tags, - 'user': request.user, + "favorites": favorites, + "has_snipts": True, + "public": public, + "public_user": False, + "snipts": snipts, + "tags": tags, + "user": request.user, } - if 'rss' in request.GET: - context['snipts'] = context['snipts'][:20] + if "rss" in request.GET: + context["snipts"] = context["snipts"][:20] return rss(request, context) return context -@render_to('snipts/list-public.html') +@render_to("snipts/list-public.html") def list_public(request, tag_slug=None): if request.blog_user: return blog_list(request) - snipts = Snipt.objects.filter(public=True).order_by('-created') + snipts = Snipt.objects.filter(public=True).order_by("-created") if tag_slug: snipts = snipts.filter(tags__slug__in=[tag_slug]) @@ -179,21 +185,16 @@ def list_public(request, tag_slug=None): else: tag = None - context = { - 'has_snipts': True, - 'public': True, - 'snipts': snipts, - 'tag': tag, - } + context = {"has_snipts": True, "public": True, "snipts": snipts, "tag": tag} - if 'rss' in request.GET: - context['snipts'] = context['snipts'][:20] + if "rss" in request.GET: + context["snipts"] = context["snipts"][:20] return rss(request, context) return context -@render_to('snipts/list-user.html') +@render_to("snipts/list-user.html") def list_user(request, username_or_custom_slug, tag_slug=None): if request.blog_user: @@ -208,15 +209,16 @@ def list_user(request, username_or_custom_slug, tag_slug=None): tags = Tag.objects snipts = Snipt.objects - if user == request.user or \ - (request.GET.get('api_key') == user.api_key.key) or \ - (user.profile.is_a_team and - user.team.user_is_member(request.user)): + if ( + user == request.user + or (request.GET.get("api_key") == user.api_key.key) + or (user.profile.is_a_team and user.team.user_is_member(request.user)) + ): public = False - favorites = Favorite.objects.filter(user=user).values('snipt') - favorites = [f['snipt'] for f in favorites] + favorites = Favorite.objects.filter(user=user).values("snipt") + favorites = [f["snipt"] for f in favorites] snipts = snipts.filter(Q(user=user) | Q(pk__in=favorites)) tags = tags.filter(snipt__user=user).distinct() @@ -226,8 +228,8 @@ def list_user(request, username_or_custom_slug, tag_slug=None): snipts = snipts.filter(user=user, public=True) public = True - tags = tags.order_by('name') - snipts = snipts.order_by('-created') + tags = tags.order_by("name") + snipts = snipts.order_by("-created") if tag_slug: snipts = snipts.filter(tags__slug__in=[tag_slug]) @@ -236,21 +238,21 @@ def list_user(request, username_or_custom_slug, tag_slug=None): tag = None if tag is None: - snipts = snipts.exclude(tags__name__in=['tmp']) + snipts = snipts.exclude(tags__name__in=["tmp"]) context = { - 'has_snipts': True, - 'public': public, - 'public_user': (public and user), - 'snipts': snipts, - 'tags': tags, - 'tag': tag, - 'user': user, - 'users_for_full_page': ['robertbanh'], + "has_snipts": True, + "public": public, + "public_user": (public and user), + "snipts": snipts, + "tags": tags, + "tag": tag, + "user": user, + "users_for_full_page": ["robertbanh"], } - if 'rss' in request.GET: - context['snipts'] = context['snipts'][:20] + if "rss" in request.GET: + context["snipts"] = context["snipts"][:20] return rss(request, context) return context @@ -261,7 +263,7 @@ def raw(request, snipt_key, lexer=None): if request.user == snipt.user: if lexer: - lexer = lexer.strip('/') + lexer = lexer.strip("/") if lexer != snipt.lexer: @@ -274,67 +276,73 @@ def raw(request, snipt_key, lexer=None): snipt.lexer = lexer snipt.save() - content_type = 'text/plain' + content_type = "text/plain" - if 'nice' in request.GET: - content_type = 'text/html' + if "nice" in request.GET: + content_type = "text/html" - return render(request, - 'snipts/raw.html', - {'snipt': snipt}, - content_type=content_type) + return render( + request, "snipts/raw.html", {"snipt": snipt}, content_type=content_type + ) def rss(request, context): - return render(request, - 'rss.xml', - context, - content_type="application/rss+xml") + return render(request, "rss.xml", context, content_type="application/rss+xml") @never_cache -def search(request, template='search/search.html', load_all=True, - form_class=ModelSearchForm, searchqueryset=None, - context_class=RequestContext, extra_context=None, - results_per_page=None): +def search( + request, + template="search/search.html", + load_all=True, + form_class=ModelSearchForm, + searchqueryset=None, + context_class=RequestContext, + extra_context=None, + results_per_page=None, +): - query = '' + query = "" results = EmptySearchQuerySet() - if request.GET.get('q'): + if request.GET.get("q"): - searchqueryset = SearchQuerySet() \ - .filter(Q(public=True) | Q(author=request.user)) \ - .order_by('-pub_date') + searchqueryset = ( + SearchQuerySet() + .filter(Q(public=True) | Q(author=request.user)) + .order_by("-pub_date") + ) - if request.user.is_authenticated() and \ - 'mine-only' in request.GET: - searchqueryset = SearchQuerySet().filter(author=request.user) \ - .order_by('-pub_date') + if request.user.is_authenticated() and "mine-only" in request.GET: + searchqueryset = ( + SearchQuerySet().filter(author=request.user).order_by("-pub_date") + ) - elif request.user.is_authenticated() and \ - ('author' in request.GET and - request.GET.get('author')): + elif request.user.is_authenticated() and ( + "author" in request.GET and request.GET.get("author") + ): - author = request.GET.get('author') + author = request.GET.get("author") if author == request.user.username: - searchqueryset = SearchQuerySet().filter(author=request.user) \ - .order_by('-pub_date') + searchqueryset = ( + SearchQuerySet().filter(author=request.user).order_by("-pub_date") + ) else: team = get_object_or_None(Team, slug=author) if team and team.user_is_member(request.user): - searchqueryset = SearchQuerySet().filter(author=team) \ - .order_by('-pub_date') + searchqueryset = ( + SearchQuerySet().filter(author=team).order_by("-pub_date") + ) - form = ModelSearchForm(request.GET, - searchqueryset=searchqueryset, - load_all=load_all) + form = ModelSearchForm( + request.GET, searchqueryset=searchqueryset, load_all=load_all + ) if form.is_valid(): - query = form.cleaned_data['q'] + query = form.cleaned_data["q"] results = form.search() else: form = form_class(searchqueryset=searchqueryset, load_all=load_all) @@ -342,21 +350,21 @@ def search(request, template='search/search.html', load_all=True, paginator = Paginator(results, results_per_page or RESULTS_PER_PAGE) try: - page = paginator.page(int(request.GET.get('page', 1))) + page = paginator.page(int(request.GET.get("page", 1))) except InvalidPage: raise Http404("No such page of results!") context = { - 'form': form, - 'has_snipts': True, - 'page': page, - 'paginator': paginator, - 'query': query, - 'suggestion': None, + "form": form, + "has_snipts": True, + "page": page, + "paginator": paginator, + "query": query, + "suggestion": None, } if results.query.backend.include_spelling: - context['suggestion'] = form.get_suggestion() + context["suggestion"] = form.get_suggestion() if extra_context: context.update(extra_context) @@ -370,13 +378,13 @@ def redirect_snipt(request, snipt_key, lexer=None): def redirect_public_tag_feed(request, tag_slug): - return HttpResponseRedirect('/public/tag/{}/?rss'.format(tag_slug)) + return HttpResponseRedirect("/public/tag/{}/?rss".format(tag_slug)) def redirect_user_feed(request, username): user = get_object_or_404(User, username=username) - return HttpResponseRedirect(user.get_absolute_url() + '?rss') + return HttpResponseRedirect(user.get_absolute_url() + "?rss") def redirect_user_tag_feed(request, username, tag_slug): - return HttpResponseRedirect(u'/{}/tag/{}/?rss'.format(username, tag_slug)) + return HttpResponseRedirect(u"/{}/tag/{}/?rss".format(username, tag_slug)) diff --git a/teams/admin.py b/teams/admin.py index 2cecf13..5ebb219 100644 --- a/teams/admin.py +++ b/teams/admin.py @@ -3,7 +3,8 @@ from teams.models import Team class TeamAdmin(admin.ModelAdmin): - list_display = ('name', 'owner', 'created', 'modified') - ordering = ('-created',) + list_display = ("name", "owner", "created", "modified") + ordering = ("-created",) + admin.site.register(Team, TeamAdmin) diff --git a/teams/migrations/0001_initial.py b/teams/migrations/0001_initial.py index 063e2f2..2fbc848 100644 --- a/teams/migrations/0001_initial.py +++ b/teams/migrations/0001_initial.py @@ -7,22 +7,38 @@ from django.conf import settings class Migration(migrations.Migration): - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ] + dependencies = [migrations.swappable_dependency(settings.AUTH_USER_MODEL)] operations = [ migrations.CreateModel( - name='Team', + name="Team", fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('name', models.CharField(max_length=255)), - ('slug', models.SlugField(max_length=255, blank=True)), - ('created', models.DateTimeField(auto_now_add=True)), - ('modified', models.DateTimeField(auto_now=True)), - ('members', models.ManyToManyField(related_name='member', to=settings.AUTH_USER_MODEL)), - ('owner', models.ForeignKey(related_name='owner', to=settings.AUTH_USER_MODEL)), - ('user', models.OneToOneField(to=settings.AUTH_USER_MODEL)), + ( + "id", + models.AutoField( + verbose_name="ID", + serialize=False, + auto_created=True, + primary_key=True, + ), + ), + ("name", models.CharField(max_length=255)), + ("slug", models.SlugField(max_length=255, blank=True)), + ("created", models.DateTimeField(auto_now_add=True)), + ("modified", models.DateTimeField(auto_now=True)), + ( + "members", + models.ManyToManyField( + related_name="member", to=settings.AUTH_USER_MODEL + ), + ), + ( + "owner", + models.ForeignKey( + related_name="owner", to=settings.AUTH_USER_MODEL + ), + ), + ("user", models.OneToOneField(to=settings.AUTH_USER_MODEL)), ], - ), + ) ] diff --git a/teams/migrations/0002_team_email.py b/teams/migrations/0002_team_email.py index 10b9c16..5d874be 100644 --- a/teams/migrations/0002_team_email.py +++ b/teams/migrations/0002_team_email.py @@ -6,15 +6,13 @@ from django.db import models, migrations class Migration(migrations.Migration): - dependencies = [ - ('teams', '0001_initial'), - ] + dependencies = [("teams", "0001_initial")] operations = [ migrations.AddField( - model_name='team', - name='email', - field=models.EmailField(default='nick@siftie.com', max_length=255), + model_name="team", + name="email", + field=models.EmailField(default="nick@siftie.com", max_length=255), preserve_default=False, - ), + ) ] diff --git a/teams/migrations/0003_auto_20150818_0057.py b/teams/migrations/0003_auto_20150818_0057.py index 844de1d..9b7c18f 100644 --- a/teams/migrations/0003_auto_20150818_0057.py +++ b/teams/migrations/0003_auto_20150818_0057.py @@ -7,14 +7,14 @@ from django.conf import settings class Migration(migrations.Migration): - dependencies = [ - ('teams', '0002_team_email'), - ] + dependencies = [("teams", "0002_team_email")] operations = [ migrations.AlterField( - model_name='team', - name='user', - field=models.OneToOneField(null=True, blank=True, to=settings.AUTH_USER_MODEL), - ), + model_name="team", + name="user", + field=models.OneToOneField( + null=True, blank=True, to=settings.AUTH_USER_MODEL + ), + ) ] diff --git a/teams/migrations/0004_auto_20150930_1526.py b/teams/migrations/0004_auto_20150930_1526.py index 3bf446f..f9d3b22 100644 --- a/teams/migrations/0004_auto_20150930_1526.py +++ b/teams/migrations/0004_auto_20150930_1526.py @@ -7,14 +7,14 @@ from django.conf import settings class Migration(migrations.Migration): - dependencies = [ - ('teams', '0003_auto_20150818_0057'), - ] + dependencies = [("teams", "0003_auto_20150818_0057")] operations = [ migrations.AlterField( - model_name='team', - name='members', - field=models.ManyToManyField(related_name='member', to=settings.AUTH_USER_MODEL, blank=True), - ), + model_name="team", + name="members", + field=models.ManyToManyField( + related_name="member", to=settings.AUTH_USER_MODEL, blank=True + ), + ) ] diff --git a/teams/migrations/0005_auto_20150930_2124.py b/teams/migrations/0005_auto_20150930_2124.py index c5e146a..10bf57b 100644 --- a/teams/migrations/0005_auto_20150930_2124.py +++ b/teams/migrations/0005_auto_20150930_2124.py @@ -6,19 +6,15 @@ from django.db import models, migrations class Migration(migrations.Migration): - dependencies = [ - ('teams', '0004_auto_20150930_1526'), - ] + dependencies = [("teams", "0004_auto_20150930_1526")] operations = [ migrations.AddField( - model_name='team', - name='stripe_id', + model_name="team", + name="stripe_id", field=models.CharField(max_length=100, null=True, blank=True), ), migrations.AlterField( - model_name='team', - name='name', - field=models.CharField(max_length=30), + model_name="team", name="name", field=models.CharField(max_length=30) ), ] diff --git a/teams/migrations/0006_team_plan.py b/teams/migrations/0006_team_plan.py index 7bf5c10..f2b2c6a 100644 --- a/teams/migrations/0006_team_plan.py +++ b/teams/migrations/0006_team_plan.py @@ -6,14 +6,25 @@ from django.db import models, migrations class Migration(migrations.Migration): - dependencies = [ - ('teams', '0005_auto_20150930_2124'), - ] + dependencies = [("teams", "0005_auto_20150930_2124")] operations = [ migrations.AddField( - model_name='team', - name='plan', - field=models.CharField(default=b'snipt-teams-25-monthly', max_length=100, choices=[(b'snipt-teams-25-monthly', b'25 users, monthly'), (b'snipt-teams-100-monthly', b'100 users, monthly'), (b'snipt-teams-250-monthly', b'250 users, monthly'), (b'snipt-teams-unlimited-monthly', b'Unlimited users, monthly'), (b'snipt-teams-25-yearly', b'25 users, yearly'), (b'snipt-teams-100-yearly', b'100 users, yearly'), (b'snipt-teams-250-yearly', b'250 users, yearly'), (b'snipt-teams-unlimited-yearly', b'Unlimited users, yearly')]), - ), + model_name="team", + name="plan", + field=models.CharField( + default=b"snipt-teams-25-monthly", + max_length=100, + choices=[ + (b"snipt-teams-25-monthly", b"25 users, monthly"), + (b"snipt-teams-100-monthly", b"100 users, monthly"), + (b"snipt-teams-250-monthly", b"250 users, monthly"), + (b"snipt-teams-unlimited-monthly", b"Unlimited users, monthly"), + (b"snipt-teams-25-yearly", b"25 users, yearly"), + (b"snipt-teams-100-yearly", b"100 users, yearly"), + (b"snipt-teams-250-yearly", b"250 users, yearly"), + (b"snipt-teams-unlimited-yearly", b"Unlimited users, yearly"), + ], + ), + ) ] diff --git a/teams/migrations/0007_team_disabled.py b/teams/migrations/0007_team_disabled.py index 2194639..219116a 100644 --- a/teams/migrations/0007_team_disabled.py +++ b/teams/migrations/0007_team_disabled.py @@ -6,14 +6,10 @@ from django.db import models, migrations class Migration(migrations.Migration): - dependencies = [ - ('teams', '0006_team_plan'), - ] + dependencies = [("teams", "0006_team_plan")] operations = [ migrations.AddField( - model_name='team', - name='disabled', - field=models.BooleanField(default=False), - ), + model_name="team", name="disabled", field=models.BooleanField(default=False) + ) ] diff --git a/teams/migrations/0008_auto_20151018_2053.py b/teams/migrations/0008_auto_20151018_2053.py index fa12c5d..2866c90 100644 --- a/teams/migrations/0008_auto_20151018_2053.py +++ b/teams/migrations/0008_auto_20151018_2053.py @@ -6,14 +6,27 @@ from django.db import models, migrations class Migration(migrations.Migration): - dependencies = [ - ('teams', '0007_team_disabled'), - ] + dependencies = [("teams", "0007_team_disabled")] operations = [ migrations.AlterField( - model_name='team', - name='plan', - field=models.CharField(default=b'snipt-teams-25-monthly', max_length=100, null=True, blank=True, choices=[(b'snipt-teams-25-monthly', b'25 users, monthly'), (b'snipt-teams-100-monthly', b'100 users, monthly'), (b'snipt-teams-250-monthly', b'250 users, monthly'), (b'snipt-teams-unlimited-monthly', b'Unlimited users, monthly'), (b'snipt-teams-25-yearly', b'25 users, yearly'), (b'snipt-teams-100-yearly', b'100 users, yearly'), (b'snipt-teams-250-yearly', b'250 users, yearly'), (b'snipt-teams-unlimited-yearly', b'Unlimited users, yearly')]), - ), + model_name="team", + name="plan", + field=models.CharField( + default=b"snipt-teams-25-monthly", + max_length=100, + null=True, + blank=True, + choices=[ + (b"snipt-teams-25-monthly", b"25 users, monthly"), + (b"snipt-teams-100-monthly", b"100 users, monthly"), + (b"snipt-teams-250-monthly", b"250 users, monthly"), + (b"snipt-teams-unlimited-monthly", b"Unlimited users, monthly"), + (b"snipt-teams-25-yearly", b"25 users, yearly"), + (b"snipt-teams-100-yearly", b"100 users, yearly"), + (b"snipt-teams-250-yearly", b"250 users, yearly"), + (b"snipt-teams-unlimited-yearly", b"Unlimited users, yearly"), + ], + ), + ) ] diff --git a/teams/migrations/0009_auto_20160512_1058.py b/teams/migrations/0009_auto_20160512_1058.py index 6db7a4f..2047f83 100644 --- a/teams/migrations/0009_auto_20160512_1058.py +++ b/teams/migrations/0009_auto_20160512_1058.py @@ -6,14 +6,27 @@ from django.db import models, migrations class Migration(migrations.Migration): - dependencies = [ - ('teams', '0008_auto_20151018_2053'), - ] + dependencies = [("teams", "0008_auto_20151018_2053")] operations = [ migrations.AlterField( - model_name='team', - name='plan', - field=models.CharField(max_length=100, choices=[('snipt-teams-25-monthly', '25 users, monthly'), ('snipt-teams-100-monthly', '100 users, monthly'), ('snipt-teams-250-monthly', '250 users, monthly'), ('snipt-teams-unlimited-monthly', 'Unlimited users, monthly'), ('snipt-teams-25-yearly', '25 users, yearly'), ('snipt-teams-100-yearly', '100 users, yearly'), ('snipt-teams-250-yearly', '250 users, yearly'), ('snipt-teams-unlimited-yearly', 'Unlimited users, yearly')], blank=True, null=True, default='snipt-teams-25-monthly'), - ), + model_name="team", + name="plan", + field=models.CharField( + max_length=100, + choices=[ + ("snipt-teams-25-monthly", "25 users, monthly"), + ("snipt-teams-100-monthly", "100 users, monthly"), + ("snipt-teams-250-monthly", "250 users, monthly"), + ("snipt-teams-unlimited-monthly", "Unlimited users, monthly"), + ("snipt-teams-25-yearly", "25 users, yearly"), + ("snipt-teams-100-yearly", "100 users, yearly"), + ("snipt-teams-250-yearly", "250 users, yearly"), + ("snipt-teams-unlimited-yearly", "Unlimited users, yearly"), + ], + blank=True, + null=True, + default="snipt-teams-25-monthly", + ), + ) ] diff --git a/teams/models.py b/teams/models.py index b6831e7..d675e08 100644 --- a/teams/models.py +++ b/teams/models.py @@ -6,25 +6,32 @@ from snipts.utils import slugify_uniquely class Team(models.Model): PLANS = ( - ('snipt-teams-25-monthly', '25 users, monthly'), - ('snipt-teams-100-monthly', '100 users, monthly'), - ('snipt-teams-250-monthly', '250 users, monthly'), - ('snipt-teams-unlimited-monthly', 'Unlimited users, monthly'), - ('snipt-teams-25-yearly', '25 users, yearly'), - ('snipt-teams-100-yearly', '100 users, yearly'), - ('snipt-teams-250-yearly', '250 users, yearly'), - ('snipt-teams-unlimited-yearly', 'Unlimited users, yearly'), + ("snipt-teams-25-monthly", "25 users, monthly"), + ("snipt-teams-100-monthly", "100 users, monthly"), + ("snipt-teams-250-monthly", "250 users, monthly"), + ("snipt-teams-unlimited-monthly", "Unlimited users, monthly"), + ("snipt-teams-25-yearly", "25 users, yearly"), + ("snipt-teams-100-yearly", "100 users, yearly"), + ("snipt-teams-250-yearly", "250 users, yearly"), + ("snipt-teams-unlimited-yearly", "Unlimited users, yearly"), ) email = models.EmailField(max_length=255) - members = models.ManyToManyField(User, related_name='member', blank=True) + members = models.ManyToManyField(User, related_name="member", blank=True) name = models.CharField(max_length=30) - owner = models.ForeignKey(User, related_name='owner', on_delete=models.DO_NOTHING) + owner = models.ForeignKey(User, related_name="owner", on_delete=models.DO_NOTHING) slug = models.SlugField(max_length=255, blank=True) stripe_id = models.CharField(max_length=100, null=True, blank=True) - user = models.OneToOneField(User, blank=True, null=True, on_delete=models.DO_NOTHING) - plan = models.CharField(max_length=100, default='snipt-teams-25-monthly', - choices=PLANS, blank=True, null=True) + user = models.OneToOneField( + User, blank=True, null=True, on_delete=models.DO_NOTHING + ) + plan = models.CharField( + max_length=100, + default="snipt-teams-25-monthly", + choices=PLANS, + blank=True, + null=True, + ) disabled = models.BooleanField(default=False) created = models.DateTimeField(auto_now_add=True, editable=False) @@ -32,7 +39,7 @@ class Team(models.Model): def save(self, *args, **kwargs): if not self.slug: - self.slug = slugify_uniquely(self.name, User, 'username') + self.slug = slugify_uniquely(self.name, User, "username") return super(Team, self).save(*args, **kwargs) def __unicode__(self): @@ -49,18 +56,18 @@ class Team(models.Model): return 0 plan_map = { - 'snipt-teams-25-monthly': 25, - 'snipt-teams-100-monthly': 100, - 'snipt-teams-250-monthly': 250, - 'snipt-teams-unlimited-monthly': float('inf'), - 'snipt-teams-25-yearly': 25, - 'snipt-teams-100-yearly': 100, - 'snipt-teams-250-yearly': 250, - 'snipt-teams-unlimited-yearly': float('inf') + "snipt-teams-25-monthly": 25, + "snipt-teams-100-monthly": 100, + "snipt-teams-250-monthly": 250, + "snipt-teams-unlimited-monthly": float("inf"), + "snipt-teams-25-yearly": 25, + "snipt-teams-100-yearly": 100, + "snipt-teams-250-yearly": 250, + "snipt-teams-unlimited-yearly": float("inf"), } - if plan_map[self.plan] == float('inf'): - return 'Unlimited' + if plan_map[self.plan] == float("inf"): + return "Unlimited" else: return plan_map[self.plan] diff --git a/teams/urls.py b/teams/urls.py index eccc9e5..3c158a3 100644 --- a/teams/urls.py +++ b/teams/urls.py @@ -3,15 +3,17 @@ from teams import views urlpatterns = [ - url(r'^for-teams/$', views.for_teams), - url(r'^for-teams/complete/$', views.for_teams_complete), - url(r'^(?P[^/]+)/members/remove/(?P[^/]+)/$', - views.remove_team_member, - name='remove-team-member'), - url(r'^(?P[^/]+)/members/add/(?P[^/]+)/$', - views.add_team_member, - name='add-team-member'), - url(r'^(?P[^/]+)/members/$', - views.team_members, - name='team-members') - ] + url(r"^for-teams/$", views.for_teams), + url(r"^for-teams/complete/$", views.for_teams_complete), + url( + r"^(?P[^/]+)/members/remove/(?P[^/]+)/$", + views.remove_team_member, + name="remove-team-member", + ), + url( + r"^(?P[^/]+)/members/add/(?P[^/]+)/$", + views.add_team_member, + name="add-team-member", + ), + url(r"^(?P[^/]+)/members/$", views.team_members, name="team-members"), +] diff --git a/teams/views.py b/teams/views.py index eb79e64..dd68786 100644 --- a/teams/views.py +++ b/teams/views.py @@ -8,7 +8,7 @@ from django.shortcuts import get_object_or_404 from teams.models import Team -@render_to('teams/for-teams.html') +@render_to("teams/for-teams.html") def for_teams(request): if request.user.is_authenticated(): profile = request.user.profile @@ -18,38 +18,34 @@ def for_teams(request): @login_required -@render_to('teams/for-teams-complete.html') +@render_to("teams/for-teams-complete.html") def for_teams_complete(request): - if request.method == 'POST' and request.user.is_authenticated(): + if request.method == "POST" and request.user.is_authenticated(): - team = Team(name=request.POST['team-name'], - email=request.POST['email'], - owner=request.user) + team = Team( + name=request.POST["team-name"], + email=request.POST["email"], + owner=request.user, + ) team.save() - user = User.objects.create_user(team.slug, - team.email, - str(uuid.uuid4())) + user = User.objects.create_user(team.slug, team.email, str(uuid.uuid4())) team.user = user team.save() - return { - 'team': team - } + return {"team": team} else: return HttpResponseBadRequest() @login_required -@render_to('teams/team-members.html') +@render_to("teams/team-members.html") def team_members(request, username): team = get_object_or_404(Team, slug=username, disabled=False) if not team.user_is_member(request.user): raise Http404 - return { - 'team': team - } + return {"team": team} @login_required @@ -57,15 +53,14 @@ def add_team_member(request, username, member): team = get_object_or_404(Team, slug=username, disabled=False) user = get_object_or_404(User, username=member) - if (team.owner != request.user): + if team.owner != request.user: raise Http404 - if ((team.members.all().count() + 1) > team.member_limit): - return HttpResponseRedirect('/' + team.slug + - '/members/?limit-reached') + if (team.members.all().count() + 1) > team.member_limit: + return HttpResponseRedirect("/" + team.slug + "/members/?limit-reached") else: team.members.add(user) - return HttpResponseRedirect('/' + team.slug + '/members/') + return HttpResponseRedirect("/" + team.slug + "/members/") @login_required @@ -73,9 +68,9 @@ def remove_team_member(request, username, member): team = get_object_or_404(Team, slug=username, disabled=False) user = get_object_or_404(User, username=member) - if (team.owner != request.user): + if team.owner != request.user: raise Http404 team.members.remove(user) - return HttpResponseRedirect('/' + team.slug + '/members/') + return HttpResponseRedirect("/" + team.slug + "/members/") diff --git a/urls.py b/urls.py index d103dd4..a6adf0d 100644 --- a/urls.py +++ b/urls.py @@ -6,21 +6,25 @@ from django.contrib.auth.views import login from django.http import HttpResponseRedirect from django.views.generic import TemplateView from django.views.static import serve -from snipts.api import (PublicSniptResource, - PublicUserResource, PrivateSniptResource, - PrivateFavoriteResource, PrivateUserProfileResource, - PrivateUserResource, PublicTagResource) +from snipts.api import ( + PublicSniptResource, + PublicUserResource, + PrivateSniptResource, + PrivateFavoriteResource, + PrivateUserProfileResource, + PrivateUserResource, + PublicTagResource, +) from snipts.views import search from tastypie.api import Api -from views import (homepage, lexers, login_redirect, - tags, user_api_key) +from views import homepage, lexers, login_redirect, tags, user_api_key -public_api = Api(api_name='public') +public_api = Api(api_name="public") public_api.register(PublicSniptResource()) public_api.register(PublicTagResource()) public_api.register(PublicUserResource()) -private_api = Api(api_name='private') +private_api = Api(api_name="private") private_api.register(PrivateSniptResource()) private_api.register(PrivateUserResource()) private_api.register(PrivateFavoriteResource()) @@ -30,37 +34,39 @@ urlpatterns = [] if os.environ.get("DISABLE_SIGNUP") == "true": urlpatterns += [ - url(r'^register/?$', lambda x: HttpResponseRedirect('/404/')), - url(r'^signup/?$', lambda x: HttpResponseRedirect('/404/')), + url(r"^register/?$", lambda x: HttpResponseRedirect("/404/")), + url(r"^signup/?$", lambda x: HttpResponseRedirect("/404/")), ] else: - urlpatterns += [ - url(r'^signup/?$', lambda x: HttpResponseRedirect('/register/')), - ] + urlpatterns += [url(r"^signup/?$", lambda x: HttpResponseRedirect("/register/"))] urlpatterns += [ - url(r'^$', homepage), - url(r'', include('registration.backends.simple.urls')), - url(r'^login/?$', login, name='login'), - url(r'^login-redirect/$', login_redirect), - url(r'^admin/', include(admin.site.urls)), - url(r'^404/$', TemplateView.as_view(template_name='404.html')), - url(r'^500/$', TemplateView.as_view(template_name='500.html')), - url(r'^robots.txt$', TemplateView.as_view(template_name='robots.txt')), - url(r'^tags/$', tags), - url(r'^account/', include('accounts.urls')), - url(r'^api/public/lexer/$', lexers), - url(r'^api/private/key/$', user_api_key), - url(r'^api/', include(public_api.urls)), - url(r'^api/', include(private_api.urls)), - url(r'^search/$', search), - url(r'^', include('teams.urls')), - url(r'^', include('snipts.urls')), - url(r'^(?Pfavicon\.ico)$', serve, { - 'document_root': os.path.join(os.path.dirname(__file__), 'static/img') - }), - url(r'^static/(?P.*)$', serve, { - 'document_root': os.path.join(os.path.dirname(__file__), 'media') - }) + url(r"^$", homepage), + url(r"", include("registration.backends.simple.urls")), + url(r"^login/?$", login, name="login"), + url(r"^login-redirect/$", login_redirect), + url(r"^admin/", include(admin.site.urls)), + url(r"^404/$", TemplateView.as_view(template_name="404.html")), + url(r"^500/$", TemplateView.as_view(template_name="500.html")), + url(r"^robots.txt$", TemplateView.as_view(template_name="robots.txt")), + url(r"^tags/$", tags), + url(r"^account/", include("accounts.urls")), + url(r"^api/public/lexer/$", lexers), + url(r"^api/private/key/$", user_api_key), + url(r"^api/", include(public_api.urls)), + url(r"^api/", include(private_api.urls)), + url(r"^search/$", search), + url(r"^", include("teams.urls")), + url(r"^", include("snipts.urls")), + url( + r"^(?Pfavicon\.ico)$", + serve, + {"document_root": os.path.join(os.path.dirname(__file__), "static/img")}, + ), + url( + r"^static/(?P.*)$", + serve, + {"document_root": os.path.join(os.path.dirname(__file__), "media")}, + ), ] diff --git a/user-admin/admin.py b/user-admin/admin.py index bf0016d..07a077f 100644 --- a/user-admin/admin.py +++ b/user-admin/admin.py @@ -4,11 +4,20 @@ from django.contrib.auth.models import User class UserAdmin(UserAdmin): - list_display = ['username', 'email', 'first_name', 'last_name', - 'last_login', 'date_joined', 'is_active', 'is_staff', - 'api_key'] - list_filter = ['is_staff', 'is_superuser', 'is_active'] - ordering = ['-date_joined'] + list_display = [ + "username", + "email", + "first_name", + "last_name", + "last_login", + "date_joined", + "is_active", + "is_staff", + "api_key", + ] + list_filter = ["is_staff", "is_superuser", "is_active"] + ordering = ["-date_joined"] + admin.site.unregister(User) admin.site.register(User, UserAdmin) diff --git a/utils/backends.py b/utils/backends.py index aec16b1..a12dea3 100644 --- a/utils/backends.py +++ b/utils/backends.py @@ -3,10 +3,10 @@ from django.contrib.auth.models import User class EmailOrUsernameModelBackend(object): def authenticate(self, username=None, password=None): - if '@' in username: - kwargs = {'email': username} + if "@" in username: + kwargs = {"email": username} else: - kwargs = {'username': username} + kwargs = {"username": username} try: user = User.objects.get(**kwargs) if user.check_password(password): diff --git a/utils/forms.py b/utils/forms.py index 80ede7f..6cb547e 100644 --- a/utils/forms.py +++ b/utils/forms.py @@ -9,34 +9,36 @@ class SniptRegistrationForm(RegistrationForm): Subclass of ``RegistrationForm`` which enforces uniqueness of email addresses and further restricts usernames. """ + def clean_username(self): """ Validate that the username is alphanumeric and is not already in use. """ - existing = User.objects.filter( - username__iexact=self.cleaned_data['username']) + existing = User.objects.filter(username__iexact=self.cleaned_data["username"]) if existing.exists(): - raise forms.ValidationError( - _("A user with that username already exists.")) + raise forms.ValidationError(_("A user with that username already exists.")) - elif '@' in self.cleaned_data['username']: + elif "@" in self.cleaned_data["username"]: raise forms.ValidationError(_("Cannot have '@' in username.")) - elif '.' in self.cleaned_data['username']: + elif "." in self.cleaned_data["username"]: raise forms.ValidationError(_("Cannot have '.' in username.")) - elif '+' in self.cleaned_data['username']: + elif "+" in self.cleaned_data["username"]: raise forms.ValidationError(_("Cannot have '+' in username.")) else: - return self.cleaned_data['username'] + return self.cleaned_data["username"] def clean_email(self): """ Validate that the supplied email address is unique for the site. """ - if User.objects.filter(email__iexact=self.cleaned_data['email']): + if User.objects.filter(email__iexact=self.cleaned_data["email"]): raise forms.ValidationError( - _("""This email address is already in use. Please supply a - different email address.""")) - return self.cleaned_data['email'] + _( + """This email address is already in use. Please supply a + different email address.""" + ) + ) + return self.cleaned_data["email"] diff --git a/utils/templatetags/pygmentize.py b/utils/templatetags/pygmentize.py index a9964c5..6e356cb 100644 --- a/utils/templatetags/pygmentize.py +++ b/utils/templatetags/pygmentize.py @@ -8,11 +8,10 @@ register = template.Library() @register.filter def pygmentize(text): - return highlight(text, - get_lexer_by_name('diff', - encoding='UTF-8'), - HtmlFormatter(linenos='table', - anchorlinenos=True, - lineanchors='L', - linespans='L', - )) + return highlight( + text, + get_lexer_by_name("diff", encoding="UTF-8"), + HtmlFormatter( + linenos="table", anchorlinenos=True, lineanchors="L", linespans="L" + ), + ) diff --git a/utils/templatetags/truncate_lines.py b/utils/templatetags/truncate_lines.py index 1678993..dcb4e6d 100644 --- a/utils/templatetags/truncate_lines.py +++ b/utils/templatetags/truncate_lines.py @@ -5,4 +5,4 @@ register = template.Library() @register.filter def truncate_lines(text): - return '\n'.join(text.split('\n')[:300]) + return "\n".join(text.split("\n")[:300]) diff --git a/utils/templatetags/verbatim.py b/utils/templatetags/verbatim.py index f2057c4..6926a6b 100644 --- a/utils/templatetags/verbatim.py +++ b/utils/templatetags/verbatim.py @@ -17,7 +17,6 @@ register = template.Library() class VerbatimNode(template.Node): - def __init__(self, text): self.text = text @@ -30,15 +29,15 @@ def verbatim(parser, token): text = [] while 1: token = parser.tokens.pop(0) - if token.contents == 'endverbatim': + if token.contents == "endverbatim": break if token.token_type == template.TOKEN_VAR: - text.append('{{') + text.append("{{") elif token.token_type == template.TOKEN_BLOCK: - text.append('{%') + text.append("{%") text.append(token.contents) if token.token_type == template.TOKEN_VAR: - text.append('}}') + text.append("}}") elif token.token_type == template.TOKEN_BLOCK: - text.append('%}') - return VerbatimNode(''.join(text)) + text.append("%}") + return VerbatimNode("".join(text)) diff --git a/utils/views.py b/utils/views.py index d116f01..39c23b8 100644 --- a/utils/views.py +++ b/utils/views.py @@ -6,10 +6,11 @@ class SniptRegistrationView(RegistrationView): """ Custom registration view that uses our custom form. """ + form_class = SniptRegistrationForm def dispatch(self, request, *args, **kwargs): return super(RegistrationView, self).dispatch(request, *args, **kwargs) def get_success_url(self, request): - return '/login-redirect' + return "/login-redirect" diff --git a/views.py b/views.py index ec0ba4b..baa8338 100644 --- a/views.py +++ b/views.py @@ -6,7 +6,7 @@ from snipts.utils import get_lexers_list from taggit.models import Tag -@render_to('homepage.html') +@render_to("homepage.html") def homepage(request): if request.blog_user: @@ -32,39 +32,32 @@ def lexers(request): except IndexError: mimetypes = [] - objects.append({ - 'name': l[0], - 'lexers': l[1], - 'filters': filters, - 'mimetypes': mimetypes - }) + objects.append( + {"name": l[0], "lexers": l[1], "filters": filters, "mimetypes": mimetypes} + ) - return {'objects': objects} + return {"objects": objects} def login_redirect(request): if request.user.is_authenticated(): - return HttpResponseRedirect('/' + request.user.username + '/') + return HttpResponseRedirect("/" + request.user.username + "/") else: - return HttpResponseRedirect('/') + return HttpResponseRedirect("/") -@render_to('tags.html') +@render_to("tags.html") def tags(request): - all_tags = Tag.objects.filter(snipt__public=True).order_by('name') - all_tags = all_tags.annotate(count=Count('taggit_taggeditem_items__id')) + all_tags = Tag.objects.filter(snipt__public=True).order_by("name") + all_tags = all_tags.annotate(count=Count("taggit_taggeditem_items__id")) popular_tags = Tag.objects.filter(snipt__public=True) - popular_tags = popular_tags.annotate( - count=Count('taggit_taggeditem_items__id')) - popular_tags = popular_tags.order_by('-count')[:20] + popular_tags = popular_tags.annotate(count=Count("taggit_taggeditem_items__id")) + popular_tags = popular_tags.order_by("-count")[:20] popular_tags = sorted(popular_tags, key=lambda tag: tag.name) - return { - 'all_tags': all_tags, - 'tags': popular_tags - } + return {"all_tags": all_tags, "tags": popular_tags} @ajax_request @@ -73,6 +66,4 @@ def user_api_key(request): if not request.user.is_authenticated(): return HttpResponseBadRequest() - return { - 'api_key': request.user.api_key.key - } + return {"api_key": request.user.api_key.key}