From 47cf4f65be6daff681ad4640c9a881f93e0804c9 Mon Sep 17 00:00:00 2001 From: Filip Todic Date: Wed, 7 Sep 2016 09:48:44 +0200 Subject: [PATCH 1/7] Update setup.py and bump version number --- setup.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/setup.py b/setup.py index 80da747..aadbaf5 100644 --- a/setup.py +++ b/setup.py @@ -1,11 +1,11 @@ #!/usr/bin/env python import os -from setuptools import setup, find_packages +from setuptools import find_packages, setup setup( name='django-unload', - version='0.1', + version='0.2', url="https://github.com/Styria-Digital/django-unload", description='Remove unused template tags', long_description=open( @@ -16,23 +16,23 @@ include_package_data=True, zip_safe=False, install_requires=[ - 'django>=1.8', + 'django>=1.8, <1.9', 'tabulate==0.7.5', ], classifiers=[ - 'Development Status :: 2 - Pre-Alpha', + 'Development Status :: 3 - Alpha', + 'Environment :: Web Environment', + 'Framework :: Django', + 'Framework :: Django :: 1.8', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: MIT License', + 'Operating System :: OS Independent', 'Programming Language :: Python', 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', - 'Environment :: Web Environment', - 'Intended Audience :: Developers', - 'License :: OSI Approved :: MIT License', - 'Operating System :: OS Independent', 'Topic :: Internet :: WWW/HTTP :: Dynamic Content', - 'Framework :: Django', ], ) From 41a1a3b425d307eabc60812cf1bfa341b653391f Mon Sep 17 00:00:00 2001 From: Filip Todic Date: Wed, 7 Sep 2016 10:17:02 +0200 Subject: [PATCH 2/7] Add setup.cfg and author to setup.py --- setup.cfg | 9 +++++++++ setup.py | 1 + 2 files changed, 10 insertions(+) create mode 100644 setup.cfg diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..1ae5b1d --- /dev/null +++ b/setup.cfg @@ -0,0 +1,9 @@ +[flake8] +exclude = build,.git,.tox +max-line-length = 100 + +[metadata] +license-file = LICENSE + +[wheel] +universal = 1 diff --git a/setup.py b/setup.py index aadbaf5..4991de8 100644 --- a/setup.py +++ b/setup.py @@ -7,6 +7,7 @@ name='django-unload', version='0.2', url="https://github.com/Styria-Digital/django-unload", + author='Styria Digital Services', description='Remove unused template tags', long_description=open( os.path.join(os.path.dirname(__file__), 'README.rst') From 708186149652b523af4352fc1dda0de814dd1b47 Mon Sep 17 00:00:00 2001 From: Filip Todic Date: Wed, 7 Sep 2016 11:32:01 +0200 Subject: [PATCH 3/7] Update documentation --- unload/base.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/unload/base.py b/unload/base.py index af8dc81..407f444 100644 --- a/unload/base.py +++ b/unload/base.py @@ -18,6 +18,23 @@ class Template(BaseTemplate): + """ + An override of Django's Template class. + + After calling the parent class, the template is analyzed for duplicates + and unnecessary loads. + + Additional attributes: + :tokens: a list of tokens found in the template + :loaded_modules: a dictionary of loaded modules + :loaded_members: a dictionary of loaded tags/filters + :used_tags: a list of custom tags used in the template + :used_filters: a list of custom filters used in the template + :tags: a dictionary of custom tags loaded into the template + :filters: a dictionary of custom filters loaded into the template + :utilized_modules: a dictionary of utilization statuses + :utilized_members: a dictionary of utilization statuses + """ def __init__(self, template_string, origin=None, name=None, engine=None): super(Template, self).__init__(template_string, origin, name, engine) From e2bd357f99fa094b41c1828227bc10b1cb5fe678 Mon Sep 17 00:00:00 2001 From: Filip Todic Date: Wed, 7 Sep 2016 11:35:51 +0200 Subject: [PATCH 4/7] Edge case: filter inside of a tag; add test templates --- .../app/templates/double_member_load.html | 7 ++++ .../templates/app/templates/only_filter.html | 6 +++ .../templates/app/templates/with_tags.html | 2 +- demo/app/templatetags/app_tags.py | 2 +- unload/tests/test_base.py | 39 ++++++++++++++++++- 5 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 demo/app/templates/app/templates/double_member_load.html create mode 100644 demo/app/templates/app/templates/only_filter.html diff --git a/demo/app/templates/app/templates/double_member_load.html b/demo/app/templates/app/templates/double_member_load.html new file mode 100644 index 0000000..01b9146 --- /dev/null +++ b/demo/app/templates/app/templates/double_member_load.html @@ -0,0 +1,7 @@ +{% extends "master.html" %} +{% load example_simple_tag plus from app_tags %} +{% load example_simple_tag plus from app_tags %} + +{% block body %} +

App template

+{% endblock body %} diff --git a/demo/app/templates/app/templates/only_filter.html b/demo/app/templates/app/templates/only_filter.html new file mode 100644 index 0000000..0b6ba8b --- /dev/null +++ b/demo/app/templates/app/templates/only_filter.html @@ -0,0 +1,6 @@ +{% extends "master.html" %} +{% load plus from app_tags %} + +{% block body %} +

Testing: {{ 2|plus:5 }}

+{% endblock body %} diff --git a/demo/app/templates/app/templates/with_tags.html b/demo/app/templates/app/templates/with_tags.html index 67cb58c..53d63f6 100644 --- a/demo/app/templates/app/templates/with_tags.html +++ b/demo/app/templates/app/templates/with_tags.html @@ -6,5 +6,5 @@

App template

{% example_inclusion_tag %}

Testing: {% example_simple_tag %}

Testing: {% example_assignment_tag as example%}

-

Testing: {{ 2|plus:5 }}

+

Testing: {% example_simple_tag 2|plus:5 %}

{% endblock body %} diff --git a/demo/app/templatetags/app_tags.py b/demo/app/templatetags/app_tags.py index d010d5c..550595b 100644 --- a/demo/app/templatetags/app_tags.py +++ b/demo/app/templatetags/app_tags.py @@ -16,7 +16,7 @@ def example_inclusion_tag(): @register.simple_tag -def example_simple_tag(): +def example_simple_tag(*args): """ An example of a simple tag. """ diff --git a/unload/tests/test_base.py b/unload/tests/test_base.py index 30466f9..012ea91 100644 --- a/unload/tests/test_base.py +++ b/unload/tests/test_base.py @@ -36,6 +36,9 @@ def setUpClass(cls): 'from_syntax_with_tags.html') cls.from_syntax_without_tags = os.path.join(app_templates, 'from_syntax_without_tags.html') + cls.double_member_load = os.path.join(app_templates, + 'double_member_load.html') + cls.only_filter = os.path.join(app_templates, 'only_filter.html') def test_get_tokens_master_template(self): master_template = Template( @@ -92,7 +95,7 @@ def test_get_tokens_with_tags(self): self.assertEqual(with_tags.tokens[10].split_contents(), ['example_assignment_tag', 'as', 'example']) self.assertEqual(with_tags.tokens[12].split_contents(), - ['2|plus:5']) + ['example_simple_tag', '2|plus:5']) self.assertEqual(with_tags.tokens[14].split_contents(), ['endblock', 'body']) @@ -150,6 +153,38 @@ def test_get_tokens_from_syntax_without_tags(self): self.assertEqual(from_syntax_without_tags.tokens[6].split_contents(), ['endblock', 'body']) + def test_get_tokens_double_member_load(self): + double_member_load = Template( + template_string=get_contents(self.double_member_load), + name=self.double_member_load) + self.assertEqual(double_member_load.tokens[0].split_contents(), + ['extends', '"master.html"']) + self.assertEqual(double_member_load.tokens[2].split_contents(), + ['load', 'example_simple_tag', 'plus', 'from', + 'app_tags']) + self.assertEqual(double_member_load.tokens[4].split_contents(), + ['load', 'example_simple_tag', 'plus', 'from', + 'app_tags']) + self.assertEqual(double_member_load.tokens[6].split_contents(), + ['block', 'body']) + self.assertEqual(double_member_load.tokens[8].split_contents(), + ['endblock', 'body']) + + def test_get_tokens_only_filter(self): + only_filter = Template( + template_string=get_contents(self.only_filter), + name=self.only_filter) + self.assertEqual(only_filter.tokens[0].split_contents(), + ['extends', '"master.html"']) + self.assertEqual(only_filter.tokens[2].split_contents(), + ['load', 'plus', 'from', 'app_tags']) + self.assertEqual(only_filter.tokens[4].split_contents(), + ['block', 'body']) + self.assertEqual(only_filter.tokens[6].split_contents(), + ['2|plus:5']) + self.assertEqual(only_filter.tokens[8].split_contents(), + ['endblock', 'body']) + def test_parse_load_block(self): master_template = Template( @@ -230,7 +265,7 @@ def test_get_used_tags_and_filters(self): name=self.with_tags) self.assertEqual(with_tags.used_tags, ['example_inclusion_tag', 'example_simple_tag', - 'example_assignment_tag']) + 'example_assignment_tag', 'example_simple_tag']) self.assertEqual(with_tags.used_filters, ['plus']) from_syntax_with_tags = Template( From 4d7f86b999bb29e23cae789d47c40e69a8ba7937 Mon Sep 17 00:00:00 2001 From: Filip Todic Date: Wed, 7 Sep 2016 13:56:09 +0200 Subject: [PATCH 5/7] Cover special cases Multiple member loads; only filters and loaded --- unload/base.py | 14 +++-- unload/tests/test_base.py | 104 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 109 insertions(+), 9 deletions(-) diff --git a/unload/base.py b/unload/base.py index 407f444..82bb077 100644 --- a/unload/base.py +++ b/unload/base.py @@ -68,17 +68,21 @@ def list_duplicates(self): lines = self.loaded_modules[module] lines_str = ', '.join(map(str, lines)) if len(lines) > 1 and lines_str not in temp_table.keys(): - temp_table[lines_str] = [module, None] + temp_table[lines_str] = [module, []] # Find duplicate member loads for member in self.loaded_members: lines = self.loaded_members[member] lines_str = ', '.join(map(str, lines)) + if len(lines) > 1: - if lines_str not in temp_table.keys(): - temp_table[lines_str] = [None, member] - else: - temp_table[lines_str][1] = member + temp_table[lines_str][1].append(member) + + for key in temp_table: + if temp_table[key][1] == []: + temp_table[key][1] = None + else: + temp_table[key][1] = '; '.join(temp_table[key][1]) # Prepare output format headers = ['Duplicate module', 'Duplicate tag/filter', 'Line number'] diff --git a/unload/tests/test_base.py b/unload/tests/test_base.py index 012ea91..b926ac3 100644 --- a/unload/tests/test_base.py +++ b/unload/tests/test_base.py @@ -147,7 +147,7 @@ def test_get_tokens_from_syntax_without_tags(self): ['extends', '"master.html"']) self.assertEqual(from_syntax_without_tags.tokens[2].split_contents(), ['load', 'example_simple_tag', 'plus', 'from', - 'app_tags']) + 'app_tags']) self.assertEqual(from_syntax_without_tags.tokens[4].split_contents(), ['block', 'body']) self.assertEqual(from_syntax_without_tags.tokens[6].split_contents(), @@ -161,10 +161,10 @@ def test_get_tokens_double_member_load(self): ['extends', '"master.html"']) self.assertEqual(double_member_load.tokens[2].split_contents(), ['load', 'example_simple_tag', 'plus', 'from', - 'app_tags']) + 'app_tags']) self.assertEqual(double_member_load.tokens[4].split_contents(), ['load', 'example_simple_tag', 'plus', 'from', - 'app_tags']) + 'app_tags']) self.assertEqual(double_member_load.tokens[6].split_contents(), ['block', 'body']) self.assertEqual(double_member_load.tokens[8].split_contents(), @@ -240,6 +240,22 @@ def test_parse_load_block(self): {'example_simple_tag': [2], 'plus': [2]}) + double_member_load = Template( + template_string=get_contents(self.double_member_load), + name=self.double_member_load) + self.assertEqual(double_member_load.loaded_modules, + {'app_tags': [2, 3]}) + self.assertEqual(double_member_load.loaded_members, + {'example_simple_tag': [2, 3], + 'plus': [2, 3]}) + + only_filter = Template( + template_string=get_contents(self.only_filter), + name=self.only_filter) + self.assertEqual(only_filter.loaded_modules, + {'app_tags': [2]}) + self.assertEqual(only_filter.loaded_members, {'plus': [2]}) + def test_get_used_tags_and_filters(self): master_template = Template( @@ -288,6 +304,18 @@ def test_get_used_tags_and_filters(self): self.assertEqual(from_syntax_without_tags.used_tags, []) self.assertEqual(from_syntax_without_tags.used_filters, []) + double_member_load = Template( + template_string=get_contents(self.double_member_load), + name=self.double_member_load) + self.assertEqual(double_member_load.used_tags, []) + self.assertEqual(double_member_load.used_filters, []) + + only_filter = Template( + template_string=get_contents(self.only_filter), + name=self.only_filter) + self.assertEqual(only_filter.used_tags, []) + self.assertEqual(only_filter.used_filters, ['plus']) + def test_get_templatetags_members(self): master_template = Template( @@ -355,6 +383,22 @@ def test_get_templatetags_members(self): self.assertIn('app_tags', from_syntax_without_tags.filters.keys()) self.assertIn('plus', from_syntax_without_tags.filters['app_tags']) + double_member_load = Template( + template_string=get_contents(self.double_member_load), + name=self.double_member_load) + self.assertIn('app_tags', double_member_load.tags.keys()) + self.assertIn('example_simple_tag', + double_member_load.tags['app_tags']) + self.assertIn('app_tags', double_member_load.filters.keys()) + self.assertIn('plus', double_member_load.filters['app_tags']) + + only_filter = Template( + template_string=get_contents(self.only_filter), + name=self.only_filter) + self.assertEqual(master_template.tags, {}) + self.assertIn('app_tags', only_filter.filters.keys()) + self.assertIn('plus', only_filter.filters['app_tags']) + def test_get_utilized_modules_and_members(self): master_template = Template( template_string=get_contents(self.master_template), @@ -408,6 +452,18 @@ def test_get_utilized_modules_and_members(self): from_syntax_without_tags.utilized_members['example_simple_tag']) self.assertFalse(from_syntax_without_tags.utilized_members['plus']) + double_member_load = Template( + template_string=get_contents(self.double_member_load), + name=self.double_member_load) + self.assertFalse(double_member_load.utilized_modules['app_tags']) + self.assertFalse(double_member_load.utilized_members['plus']) + + only_filter = Template( + template_string=get_contents(self.only_filter), + name=self.only_filter) + self.assertTrue(only_filter.utilized_modules['app_tags']) + self.assertTrue(only_filter.utilized_members['plus']) + def test_list_duplicates(self): master_template = Template( template_string=get_contents(self.master_template), @@ -459,6 +515,26 @@ def test_list_duplicates(self): ([], ['Duplicate module', 'Duplicate tag/filter', 'Line number'])) + double_member_load = Template( + template_string=get_contents(self.double_member_load), + name=self.double_member_load) + double_member_load_table,\ + double_member_load_header = double_member_load.list_duplicates() + self.assertIn('app_tags', double_member_load_table[0]) + self.assertIn('plus', double_member_load_table[0][1]) + self.assertIn('example_simple_tag', double_member_load_table[0][1]) + self.assertIn('2, 3', double_member_load_table[0]) + self.assertEqual(double_member_load_header, + ['Duplicate module', 'Duplicate tag/filter', + 'Line number']) + + only_filter = Template( + template_string=get_contents(self.only_filter), + name=self.only_filter) + self.assertEqual(only_filter.list_duplicates(), + ([], ['Duplicate module', 'Duplicate tag/filter', + 'Line number'])) + def test_list_unutilized_items(self): master_template = Template( template_string=get_contents(self.master_template), @@ -505,7 +581,27 @@ def test_list_unutilized_items(self): table, header = from_syntax_without_tags.list_unutilized_items() # Merge the two rows due to unpredictable ordering of members all_rows = table[0] + table[1] - self.assertEqual(header, ['Unutilized module', 'Unutilized tag/filter']) + self.assertEqual( + header, ['Unutilized module', 'Unutilized tag/filter']) self.assertIn('app_tags', all_rows) self.assertIn('example_simple_tag', all_rows) self.assertIn('plus', all_rows) + + double_member_load = Template( + template_string=get_contents(self.double_member_load), + name=self.double_member_load) + table, header = double_member_load.list_unutilized_items() + # Merge the two rows due to unpredictable ordering of members + all_rows = table[0] + table[1] + self.assertEqual( + header, ['Unutilized module', 'Unutilized tag/filter']) + self.assertIn('app_tags', all_rows) + self.assertIn('example_simple_tag', all_rows) + self.assertIn('plus', all_rows) + + only_filter = Template( + template_string=get_contents(self.only_filter), + name=self.only_filter) + self.assertEqual(only_filter.list_unutilized_items(), + ([], ['Unutilized module', 'Unutilized tag/filter'])) + From 97b8d5ee88830ddbf678dba32534c1036216da7b Mon Sep 17 00:00:00 2001 From: Filip Todic Date: Wed, 7 Sep 2016 14:32:18 +0200 Subject: [PATCH 6/7] Test exception and DebugLexer --- unload/base.py | 40 +++++--------------------------------- unload/tests/test_base.py | 20 +++++++++++++++++++ unload/tests/test_utils.py | 27 +++++++++++++++++++++++-- unload/utils.py | 30 ++++++++++++++++++++++++++++ 4 files changed, 80 insertions(+), 37 deletions(-) diff --git a/unload/base.py b/unload/base.py index 82bb077..0da3e95 100644 --- a/unload/base.py +++ b/unload/base.py @@ -2,19 +2,10 @@ from __future__ import unicode_literals -import sys +from django.template.base import Lexer, Template as BaseTemplate -from distutils.version import StrictVersion - -from django.template.base import ( - Lexer, Template as BaseTemplate, InvalidTemplateLibrary) - -from .settings import (DJANGO_VERSION, BUILT_IN_TAGS, BUILT_IN_TAG_VALUES, - BUILT_IN_FILTERS) -from .utils import get_filters, update_dictionary - -if StrictVersion(DJANGO_VERSION) > StrictVersion('1.8'): - from django.template.base import get_library +from .settings import BUILT_IN_TAGS, BUILT_IN_TAG_VALUES, BUILT_IN_FILTERS +from .utils import get_filters, get_templatetag_members, update_dictionary class Template(BaseTemplate): @@ -49,7 +40,8 @@ def __init__(self, template_string, origin=None, name=None, engine=None): self.used_tags = self._get_used_tags() self.used_filters = self._get_used_filters() # Get the tags and filters available to this template - self.tags, self.filters = self._get_templatetags_members() + self.tags, self.filters = get_templatetag_members( + self.name, self.loaded_modules) # Find utilized modules, tags and filters self.utilized_modules = self._get_utilized_modules() self.utilized_members = self._get_utilized_members() @@ -167,28 +159,6 @@ def _get_utilized_modules(self): return utilized_modules - def _get_templatetags_members(self): - """ - Get the names of tags and filters from available templatetags modules. - - :returns: {'somelib': [tags]}, {'somelib': [filters]} - """ - tags = {} - filters = {} - for module in self.loaded_modules: - try: - lib = get_library(module) - except InvalidTemplateLibrary: - msg = ('Unable to locate the loaded library! Library: {}; ' - 'Template: {}\n').format(module, self.name) - sys.stdout.write(msg) - tags[module] = [] - continue - tags[module] = lib.tags.keys() - filters[module] = lib.filters.keys() - - return tags, filters - def _get_tokens(self): """ Get the list of tokens from the template source. diff --git a/unload/tests/test_base.py b/unload/tests/test_base.py index b926ac3..c5486ed 100644 --- a/unload/tests/test_base.py +++ b/unload/tests/test_base.py @@ -7,6 +7,7 @@ from django.apps import apps from django.conf import settings from django.test import TestCase +from django.test.utils import override_settings from ..base import Template from ..utils import get_contents @@ -54,6 +55,25 @@ def test_get_tokens_master_template(self): self.assertEqual(master_template.tokens[7].split_contents(), ['endblock', 'body']) + @override_settings(DEBUG=True) + def test_get_tokens_master_template_debug_mode(self): + """ + The settings override is tested only once because the code using the + DebugLexer is extracted from Django's source code. + """ + master_template = Template( + template_string=get_contents(self.master_template), + name=self.master_template) + + self.assertEqual(master_template.tokens[1].split_contents(), + ['block', 'title']) + self.assertEqual(master_template.tokens[3].split_contents(), + ['endblock', 'title']) + self.assertEqual(master_template.tokens[5].split_contents(), + ['block', 'body']) + self.assertEqual(master_template.tokens[7].split_contents(), + ['endblock', 'body']) + def test_get_tokens_tag_template(self): # Test tag template tag_template = Template( diff --git a/unload/tests/test_utils.py b/unload/tests/test_utils.py index 79f8c12..89b906e 100644 --- a/unload/tests/test_utils.py +++ b/unload/tests/test_utils.py @@ -11,8 +11,8 @@ from django.test import TestCase from ..utils import (get_app, get_contents, get_filters, get_package_locations, - get_template_files, output_template_name, output_as_table, - update_dictionary) + get_template_files, get_templatetag_members, + output_template_name, output_as_table, update_dictionary) PYTHON_VERSION = sys.version_info @@ -82,6 +82,29 @@ def test_get_template_files(self): template_files = get_template_files(templates_dir) self.assertIn(master_html, template_files) + def test_get_templatetag_members(self): + output = StringIO() + template_name = 'example.html' + loaded_modules = {'app_tags': [1]} + tags, filters = get_templatetag_members(template_name, + loaded_modules, output) + self.assertEqual(1, len(tags.keys())) + self.assertIn('app_tags', tags.keys()) + self.assertIn('example_simple_tag', tags['app_tags']) + self.assertIn('example_inclusion_tag', tags['app_tags']) + self.assertIn('example_assignment_tag', tags['app_tags']) + self.assertIn('app_tags', filters.keys()) + self.assertIn('plus', filters['app_tags']) + self.assertEqual('', output.getvalue()) + + # Add a non existing templatetag modules + loaded_modules['some_lib'] = [1] + tags, filters = get_templatetag_members(template_name, + loaded_modules, output) + self.assertEqual(output.getvalue().strip(), + ('Unable to locate the loaded library! ' + 'Library: some_lib; Template: example.html')) + def test_start_output(self): """ Test output to console. diff --git a/unload/utils.py b/unload/utils.py index 40f3afd..b717717 100644 --- a/unload/utils.py +++ b/unload/utils.py @@ -5,12 +5,19 @@ import io import os import sys +from distutils.version import StrictVersion from mimetypes import guess_type from pip import get_installed_distributions from tabulate import tabulate from django.apps import apps +from django.template.base import InvalidTemplateLibrary + +from .settings import DJANGO_VERSION + +if StrictVersion(DJANGO_VERSION) > StrictVersion('1.8'): + from django.template.base import get_library def get_app(app_label): @@ -98,6 +105,29 @@ def get_template_files(template_dir): return templates +def get_templatetag_members(template_name, loaded_modules, output=sys.stdout): + """ + Get the names of tags and filters from available templatetags modules. + + :returns: {'somelib': [tags]}, {'somelib': [filters]} + """ + tags = {} + filters = {} + for module in loaded_modules: + try: + lib = get_library(module) + except InvalidTemplateLibrary: + msg = ('Unable to locate the loaded library! Library: {}; ' + 'Template: {}\n').format(module, template_name) + output.write(msg) + tags[module] = [] + continue + tags[module] = lib.tags.keys() + filters[module] = lib.filters.keys() + + return tags, filters + + def output_template_name(template_name, output=sys.stdout): """ Output the template's name. From e5aa6f598094ab656637f5b3cc3e30f0a678a1d2 Mon Sep 17 00:00:00 2001 From: Filip Todic Date: Thu, 8 Sep 2016 11:06:29 +0200 Subject: [PATCH 7/7] Update description in setup.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 4991de8..de307ac 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ version='0.2', url="https://github.com/Styria-Digital/django-unload", author='Styria Digital Services', - description='Remove unused template tags', + description='Remove unused custom Django template tags and filters', long_description=open( os.path.join(os.path.dirname(__file__), 'README.rst') ).read(),