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