diff options
author | SVN-Git Migration <python-modules-team@lists.alioth.debian.org> | 2015-10-08 11:51:45 -0700 |
---|---|---|
committer | SVN-Git Migration <python-modules-team@lists.alioth.debian.org> | 2015-10-08 11:51:45 -0700 |
commit | 2228968f3d51a3d686adb2839bf43e018432f941 (patch) | |
tree | 9e95992c4b09bbea50336e91a709a775a20fd1e5 /tagging/utils.py | |
download | python-django-tagging-2228968f3d51a3d686adb2839bf43e018432f941.tar python-django-tagging-2228968f3d51a3d686adb2839bf43e018432f941.tar.gz |
Imported Upstream version 0.1+svn102upstream/0.1+svn102
Diffstat (limited to 'tagging/utils.py')
-rw-r--r-- | tagging/utils.py | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/tagging/utils.py b/tagging/utils.py new file mode 100644 index 0000000..af50bac --- /dev/null +++ b/tagging/utils.py @@ -0,0 +1,140 @@ +import math +import re +import types + +from django.db.models.query import QuerySet +from django.utils.encoding import force_unicode, smart_unicode + +# Python 2.3 compatibility +if not hasattr(__builtins__, 'set'): + from sets import Set as set + +find_tag_re = re.compile(r'[-\w]+', re.U) + +def get_tag_name_list(tag_names): + """ + Finds tag names in the given string and return them as a list. + """ + if tag_names is not None: + tag_names = force_unicode(tag_names) + results = find_tag_re.findall(tag_names or '') + return results + +def get_tag_list(tags): + """ + Utility function for accepting tag input in a flexible manner. + + If a ``Tag`` object is given, it will be returned in a list as + its single occupant. + + If given, the tag names in the following will be used to create a + ``Tag`` ``QuerySet``: + + * A string, which may contain multiple tag names. + * A list or tuple of strings corresponding to tag names. + * A list or tuple of integers corresponding to tag ids. + + If given, the following will be returned as-is: + + * A list or tuple of ``Tag`` objects. + * A ``Tag`` ``QuerySet``. + """ + from tagging.models import Tag + if isinstance(tags, Tag): + return [tags] + elif isinstance(tags, QuerySet) and tags.model is Tag: + return tags + elif isinstance(tags, types.StringTypes): + return Tag.objects.filter(name__in=get_tag_name_list(tags)) + elif isinstance(tags, (types.ListType, types.TupleType)): + if len(tags) == 0: + return tags + contents = set() + for item in tags: + if isinstance(item, types.StringTypes): + contents.add('string') + elif isinstance(item, Tag): + contents.add('tag') + elif isinstance(item, (types.IntType, types.LongType)): + contents.add('int') + if len(contents) == 1: + if 'string' in contents: + return Tag.objects.filter(name__in=[smart_unicode(tag) \ + for tag in tags]) + elif 'tag' in contents: + return tags + elif 'int' in contents: + return Tag.objects.filter(id__in=tags) + else: + raise ValueError(u'If a list or tuple of tags is provided, they must all be tag names, Tag objects or Tag ids.') + else: + raise ValueError(u'The tag input given was invalid.') + +def get_tag(tag): + """ + Utility function for accepting single tag input in a flexible + manner. + + If a ``Tag`` object is given it will be returned as-is; if a + string or integer are given, they will be used to lookup the + appropriate ``Tag``. + + If no matching tag can be found, ``None`` will be returned. + """ + from tagging.models import Tag + if isinstance(tag, Tag): + return tag + + try: + if isinstance(tag, types.StringTypes): + return Tag.objects.get(name=tag) + elif isinstance(tag, (types.IntType, types.LongType)): + return Tag.objects.get(id=tag) + except Tag.DoesNotExist: + pass + + return None + +# Font size distribution algorithms +LOGARITHMIC, LINEAR = 1, 2 + +def calculate_cloud(tags, steps=4, distribution=LOGARITHMIC): + """ + Add a ``font_size`` attribute to each tag according to the + frequency of its use, as indicated by its ``count`` + attribute. + + ``steps`` defines the range of font sizes - ``font_size`` will + be an integer between 1 and ``steps`` (inclusive). + + ``distribution`` defines the type of font size distribution + algorithm which will be used - logarithmic or linear. It must be + either ``tagging.utils.LOGARITHMIC`` or ``tagging.utils.LINEAR``. + + The algorithm to scale the tags logarithmically is from a + blog post by Anders Pearson, 'Scaling tag clouds': + http://thraxil.com/users/anders/posts/2005/12/13/scaling-tag-clouds/ + """ + if len(tags) > 0: + thresholds = [] + counts = [tag.count for tag in tags] + max_weight = float(max(counts)) + min_weight = float(min(counts)) + + # Set up the appropriate thresholds + if distribution == LOGARITHMIC: + thresholds = [math.pow(max_weight - min_weight + 1, float(i) / float(steps)) \ + for i in range(1, steps + 1)] + elif distribution == LINEAR: + delta = (max_weight - min_weight) / float(steps) + thresholds = [min_weight + i * delta for i in range(1, steps + 1)] + else: + raise ValueError(u'Invalid font size distribution algorithm specified: %s.' % distribution) + + for tag in tags: + font_set = False + for i in range(steps): + if not font_set and tag.count <= thresholds[i]: + tag.font_size = i + 1 + font_set = True + return tags |