diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..ab4d79c --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +/drum/links/static/* linguist-vendored=true diff --git a/AUTHORS b/AUTHORS index 48f909d..3fc45b7 100644 --- a/AUTHORS +++ b/AUTHORS @@ -4,4 +4,5 @@ * Vitaliy Kharin * Alex Bendig * Rafael Capdevielle -* Micah Yoder \ No newline at end of file +* Micah Yoder +* Minwoo Park \ No newline at end of file diff --git a/README.rst b/README.rst index a2a8748..9b2978b 100644 --- a/README.rst +++ b/README.rst @@ -94,12 +94,12 @@ given title is broken up into keywords, and if those keywords already exist as tags in the database, they're applied to the newly added link. This means that for auto-tagging to work, the tags must already exist -in the database. You can either add them manually via the admin, or -if you have a large number of existing links, you can use the -``auto_tag`` management command Drum provides, which will analyse the -titles of all your existing links, and provide tags it extracts from -them. This makes use of the `topia.termextract`_ package which -you'll first need to install:: +in the database. You can either add them manually via the admin (under +the "Keywords" section), or if you have a large number of existing +links, you can use the ``auto_tag`` management command Drum provides, +which will analyse the titles of all your existing links, and provide +tags it extracts from them. This makes use of the `topia.termextract`_ +package which you'll first need to install:: python manage.py auto_tag --generate=100 --assign --remove @@ -113,6 +113,12 @@ all tags in the database to all links in the database, as would occur if they were newly created. The ``--remove`` option will cause all existing tags to be removed. +You can also define your own tag extraction function, if splitting the +title on spaces doesn't suffice. To do so, define the setting +``AUTO_TAG_FUNCTION`` which should contain a string with the Python +dotted path to your custom tag function. The function will be given an +unsaved ``Link`` object, and should return a sequence of tags to add. + Contributing ============ diff --git a/drum/__init__.py b/drum/__init__.py index 8b34414..4ec4007 100644 --- a/drum/__init__.py +++ b/drum/__init__.py @@ -1,2 +1,2 @@ -__version__ = "0.3.0" +__version__ = "0.4.0" diff --git a/drum/links/management/commands/auto_tag.py b/drum/links/management/commands/auto_tag.py index 83db6c3..3f5dd50 100644 --- a/drum/links/management/commands/auto_tag.py +++ b/drum/links/management/commands/auto_tag.py @@ -1,10 +1,9 @@ from __future__ import unicode_literals -from optparse import make_option from string import punctuation from django.db import connection -from django.core.management.base import BaseCommand +from django.core.management.base import BaseCommand, CommandError from mezzanine.generic.models import AssignedKeyword, Keyword from mezzanine.utils.urls import slugify @@ -13,15 +12,14 @@ class Command(BaseCommand): - option_list = BaseCommand.option_list + ( - make_option("--generate", dest="generate", type=int), - make_option("--remove", dest="remove", action="store_true", - default=False), - make_option("--assign", dest="assign", action="store_true", - default=False), - ) + def add_arguments(self, parser): + parser.add_argument("--generate", dest="generate", type=int) + parser.add_argument("--remove", dest="remove", action="store_true", + default=False) + parser.add_argument("--assign", dest="assign", action="store_true", + default=False) - def handle(self, *urls, **options): + def handle(self, **options): cursor = connection.cursor() if options["remove"]: cursor.execute("DELETE FROM generic_assignedkeyword;") @@ -40,8 +38,7 @@ def generate(self, size): try: from topia.termextract import extract except ImportError: - print("topia.termextract library required") - return + raise CommandError("topia.termextract library required") extractor = extract.TermExtractor() extractor.filter = extract.permissiveFilter diff --git a/drum/links/management/commands/poll_rss.py b/drum/links/management/commands/poll_rss.py index 3a6c8e7..58a5a2a 100644 --- a/drum/links/management/commands/poll_rss.py +++ b/drum/links/management/commands/poll_rss.py @@ -1,7 +1,6 @@ -from __future__ import unicode_literals +from __future__ import print_function, unicode_literals from datetime import datetime -from optparse import make_option from time import mktime from django.contrib.auth.models import User @@ -17,25 +16,25 @@ class Command(BaseCommand): - option_list = BaseCommand.option_list + ( - make_option( + def add_arguments(self, parser): + parser.add_argument("urls", nargs="*") + parser.add_argument( "--follow", action="store_true", dest="follow", default=False, help="Make a HTTP request for every link imported and follow " "redirects, storing the final URL." - ), - make_option( + ) + parser.add_argument( "--follow-old", action="store_true", dest="follow_old", default=False, help="Will go back and run --follow aginst previously added links" - ), - ) + ) - def handle(self, *urls, **options): + def handle(self, **options): if options["follow_old"]: self.follow_old() return @@ -43,22 +42,23 @@ def handle(self, *urls, **options): user_id = User.objects.filter(is_superuser=1)[0].id except IndexError: return - for url in urls: + for url in options["urls"]: for entry in parse(url).entries: link = self.entry_to_link_dict(entry) if options["follow"]: try: link["link"] = self.follow_redirects(link["link"]) except Exception as e: - print "%s - skipping %s" % (e, link["link"]) + print("%s - skipping %s" % (e, link["link"])) continue link["user_id"] = user_id try: obj = Link.objects.get(link=link["link"]) except Link.DoesNotExist: obj = Link.objects.create(**link) - obj.rating.add(Rating(value=1, user_id=user_id)) - print "Added %s" % obj + obj.rating.add(Rating(value=1, user_id=user_id), + bulk=False) + print("Added %s" % obj) def link_from_entry(self, entry): """ @@ -86,7 +86,7 @@ def entry_to_link_dict(self, entry): def follow_redirects(self, link): final = requests.get(link).url - print "followed %s to %s" % (link, final) + print("followed %s to %s" % (link, final)) return final def follow_old(self): @@ -94,6 +94,6 @@ def follow_old(self): try: new_url = self.follow_redirects(link.link) except Exception as e: - print "%s - skipping %s" % (e, link.link) + print("%s - skipping %s" % (e, link.link)) else: Link.objects.filter(id=link.id).update(link=new_url) diff --git a/drum/links/models.py b/drum/links/models.py index 9e5d098..5107cdc 100644 --- a/drum/links/models.py +++ b/drum/links/models.py @@ -2,7 +2,6 @@ from future import standard_library from future.builtins import int -from re import sub, split from time import time from operator import ior from functools import reduce @@ -16,7 +15,7 @@ from django.core.urlresolvers import reverse from django.db import models from django.db.models import Q -from django.db.models.signals import post_save, post_delete +from django.db.models.signals import post_save, pre_delete from django.dispatch import receiver from django.utils.encoding import python_2_unicode_compatible @@ -25,6 +24,7 @@ from mezzanine.core.request import current_request from mezzanine.generic.models import Rating, Keyword, AssignedKeyword from mezzanine.generic.fields import RatingField, CommentsField +from mezzanine.utils.importing import import_dotted_path from mezzanine.utils.urls import slugify @@ -54,15 +54,14 @@ def url(self): def save(self, *args, **kwargs): keywords = [] if not self.keywords_string and getattr(settings, "AUTO_TAG", False): - variations = lambda word: [word, - sub("^([^A-Za-z0-9])*|([^A-Za-z0-9]|s)*$", "", word), - sub("^([^A-Za-z0-9])*|([^A-Za-z0-9])*$", "", word)] - keywords = sum(map(variations, split("\s|/", self.title)), []) + func_name = getattr(settings, "AUTO_TAG_FUNCTION", + "drum.links.utils.auto_tag") + keywords = import_dotted_path(func_name)(self) super(Link, self).save(*args, **kwargs) if keywords: lookup = reduce(ior, [Q(title__iexact=k) for k in keywords]) for keyword in Keyword.objects.filter(lookup): - self.keywords.add(AssignedKeyword(keyword=keyword)) + self.keywords.add(AssignedKeyword(keyword=keyword), bulk=False) @python_2_unicode_compatible class Profile(models.Model): @@ -77,7 +76,7 @@ def __str__(self): @receiver(post_save, sender=Rating) -@receiver(post_delete, sender=Rating) +@receiver(pre_delete, sender=Rating) def karma(sender, **kwargs): """ Each time a rating is saved, check its value and modify the diff --git a/drum/links/templates/accounts/account_profile.html b/drum/links/templates/accounts/account_profile.html index 6d118b7..1bdd713 100644 --- a/drum/links/templates/accounts/account_profile.html +++ b/drum/links/templates/accounts/account_profile.html @@ -1,5 +1,5 @@ {% extends "base.html" %} -{% load i18n future mezzanine_tags drum_tags %} +{% load i18n mezzanine_tags drum_tags %} {% block meta_title %}{{ profile_user.username }}{% endblock %} {% block title %}{{ profile_user|get_profile }}{% endblock %} diff --git a/drum/links/templates/accounts/includes/user_panel_nav.html b/drum/links/templates/accounts/includes/user_panel_nav.html index e225599..86c3ddd 100644 --- a/drum/links/templates/accounts/includes/user_panel_nav.html +++ b/drum/links/templates/accounts/includes/user_panel_nav.html @@ -1,4 +1,4 @@ -{% load i18n future mezzanine_tags drum_tags %} +{% load i18n mezzanine_tags drum_tags %} diff --git a/drum/links/templates/admin/links/link/change_list.html b/drum/links/templates/admin/links/link/change_list.html index f89b172..81767b7 100644 --- a/drum/links/templates/admin/links/link/change_list.html +++ b/drum/links/templates/admin/links/link/change_list.html @@ -2,7 +2,7 @@ {% block extrahead %} {{ block.super }}