From befc7ad2cd074c48727a765b8c21aa591e102338 Mon Sep 17 00:00:00 2001 From: Scot Hacker Date: Fri, 12 Apr 2019 00:09:01 -0700 Subject: [PATCH] Formatting --- base_urls.py | 4 +- test_settings.py | 36 ++---- todo/__init__.py | 10 +- todo/check.py | 6 +- todo/features.py | 3 +- todo/mail/delivery.py | 12 +- todo/mail/producers/imap.py | 6 +- todo/management/commands/hopper.py | 40 ++++--- todo/management/commands/mail_worker.py | 5 +- todo/migrations/0001_initial.py | 105 +++++++++++------- todo/migrations/0002_auto_20150614_2339.py | 12 +- todo/migrations/0003_assignee_optional.py | 18 +-- todo/migrations/0004_rename_list_tasklist.py | 59 +++++----- todo/migrations/0005_auto_20180212_2325.py | 11 +- todo/migrations/0006_rename_item_model.py | 9 +- .../0007_auto_update_created_date.py | 10 +- todo/migrations/0009_priority_optional.py | 11 +- todo/migrations/0010_attachment.py | 34 ++++-- todo/models.py | 12 +- todo/operations/csv_importer.py | 8 +- todo/tests/test_tracker.py | 31 ++---- todo/tests/test_utils.py | 3 +- todo/tests/test_views.py | 1 + todo/urls.py | 99 +++++------------ todo/utils.py | 2 +- todo/views/external_add.py | 2 +- todo/views/remove_attachment.py | 9 +- todo/views/task_detail.py | 6 +- 28 files changed, 253 insertions(+), 311 deletions(-) diff --git a/base_urls.py b/base_urls.py index 24c9f32..8e3c5f5 100644 --- a/base_urls.py +++ b/base_urls.py @@ -10,6 +10,4 @@ For your project, ignore this file and add to your site's urlconf. """ -urlpatterns = [ - path('lists/', include('todo.urls')), -] +urlpatterns = [path("lists/", include("todo.urls"))] diff --git a/test_settings.py b/test_settings.py index 81007c8..4cb22ce 100644 --- a/test_settings.py +++ b/test_settings.py @@ -2,11 +2,7 @@ import os DEBUG = (True,) BASE_DIR = os.path.dirname(os.path.dirname(__file__)) -DATABASES = { - "default": { - "ENGINE": "django.db.backends.sqlite3" - } -} +DATABASES = {"default": {"ENGINE": "django.db.backends.sqlite3"}} EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend" @@ -65,28 +61,12 @@ TEMPLATES = [ ] LOGGING = { - 'version': 1, - 'disable_existing_loggers': False, - 'handlers': { - 'console': { - 'class': 'logging.StreamHandler', - }, - }, - 'loggers': { - '': { - 'handlers': ['console'], - 'level': 'DEBUG', - 'propagate': True, - }, - 'django': { - 'handlers': ['console'], - 'level': 'WARNING', - 'propagate': True, - }, - 'django.request': { - 'handlers': ['console'], - 'level': 'DEBUG', - 'propagate': True, - }, + "version": 1, + "disable_existing_loggers": False, + "handlers": {"console": {"class": "logging.StreamHandler"}}, + "loggers": { + "": {"handlers": ["console"], "level": "DEBUG", "propagate": True}, + "django": {"handlers": ["console"], "level": "WARNING", "propagate": True}, + "django.request": {"handlers": ["console"], "level": "DEBUG", "propagate": True}, }, } diff --git a/todo/__init__.py b/todo/__init__.py index c3d3df8..7139c3b 100644 --- a/todo/__init__.py +++ b/todo/__init__.py @@ -1,12 +1,12 @@ """ A multi-user, multi-group task management and assignment system for Django. """ -__version__ = '2.4.6' +__version__ = "2.4.6" -__author__ = 'Scot Hacker' -__email__ = 'shacker@birdhouse.org' +__author__ = "Scot Hacker" +__email__ = "shacker@birdhouse.org" -__url__ = 'https://github.com/shacker/django-todo' -__license__ = 'BSD License' +__url__ = "https://github.com/shacker/django-todo" +__license__ = "BSD License" from . import check diff --git a/todo/check.py b/todo/check.py index 68560ce..67ec10c 100644 --- a/todo/check.py +++ b/todo/check.py @@ -11,9 +11,7 @@ def dal_check(app_configs, **kwargs): return [] errors = [] - missing_apps = {'dal', 'dal_select2'} - set(settings.INSTALLED_APPS) + missing_apps = {"dal", "dal_select2"} - set(settings.INSTALLED_APPS) for missing_app in missing_apps: - errors.append( - Error('{} needs to be in INSTALLED_APPS'.format(missing_app)) - ) + errors.append(Error("{} needs to be in INSTALLED_APPS".format(missing_app))) return errors diff --git a/todo/features.py b/todo/features.py index 8cd084e..a6f6b3e 100644 --- a/todo/features.py +++ b/todo/features.py @@ -11,5 +11,6 @@ except ImportError: HAS_TASK_MERGE = False if HAS_AUTOCOMPLETE: import dal.autocomplete - if getattr(dal.autocomplete, 'Select2QuerySetView', None) is not None: + + if getattr(dal.autocomplete, "Select2QuerySetView", None) is not None: HAS_TASK_MERGE = True diff --git a/todo/mail/delivery.py b/todo/mail/delivery.py index 33f916f..8477172 100644 --- a/todo/mail/delivery.py +++ b/todo/mail/delivery.py @@ -1,8 +1,9 @@ import importlib + def _declare_backend(backend_path): - backend_path = backend_path.split('.') - backend_module_name = '.'.join(backend_path[:-1]) + backend_path = backend_path.split(".") + backend_module_name = ".".join(backend_path[:-1]) class_name = backend_path[-1] def backend(*args, headers={}, from_address=None, **kwargs): @@ -17,9 +18,10 @@ def _declare_backend(backend_path): _backend.from_address = from_address _backend.headers = headers return _backend + return backend -smtp_backend = _declare_backend('django.core.mail.backends.smtp.EmailBackend') -console_backend = _declare_backend('django.core.mail.backends.console.EmailBackend') -locmem_backend = _declare_backend('django.core.mail.backends.locmem.EmailBackend') +smtp_backend = _declare_backend("django.core.mail.backends.smtp.EmailBackend") +console_backend = _declare_backend("django.core.mail.backends.console.EmailBackend") +locmem_backend = _declare_backend("django.core.mail.backends.locmem.EmailBackend") diff --git a/todo/mail/producers/imap.py b/todo/mail/producers/imap.py index 977c76f..af00358 100644 --- a/todo/mail/producers/imap.py +++ b/todo/mail/producers/imap.py @@ -70,14 +70,12 @@ def imap_producer( try: yield message except Exception: - logger.exception( - f"something went wrong while processing {message_uid}" - ) + logger.exception(f"something went wrong while processing {message_uid}") raise if not preserve: # tag the message for deletion - conn.store(message_uid, '+FLAGS', '\\Deleted') + conn.store(message_uid, "+FLAGS", "\\Deleted") else: logger.debug("did not receive any message") finally: diff --git a/todo/management/commands/hopper.py b/todo/management/commands/hopper.py index 933656b..1b322bf 100644 --- a/todo/management/commands/hopper.py +++ b/todo/management/commands/hopper.py @@ -18,7 +18,7 @@ def gen_title(tc=True): # faker doesn't provide a way to generate headlines in Title Case, without periods, so make our own. # With arg `tc=True`, Title Cases The Generated Text fake = Faker() - thestr = fake.text(max_nb_chars=32).rstrip('.') + thestr = fake.text(max_nb_chars=32).rstrip(".") if tc: thestr = titlecase(thestr) @@ -29,7 +29,7 @@ def gen_content(): # faker provides paragraphs as a list; convert with linebreaks fake = Faker() grafs = fake.paragraphs() - thestr = '' + thestr = "" for g in grafs: thestr += "{}\n\n".format(g) return thestr @@ -43,11 +43,12 @@ class Command(BaseCommand): "-d", "--delete", help="Wipe out existing content before generating new.", - action="store_true") + action="store_true", + ) def handle(self, *args, **options): - if options.get('delete'): + if options.get("delete"): # Wipe out previous contents? Cascade deletes the Tasks from the TaskLists. TaskList.objects.all().delete() print("Content from previous run deleted.") @@ -56,11 +57,11 @@ class Command(BaseCommand): fake = Faker() # Use to create user's names # Create users and groups, add different users to different groups. Staff user is in both groups. - sd_group, created = Group.objects.get_or_create(name='Scuba Divers') - bw_group, created = Group.objects.get_or_create(name='Basket Weavers') + sd_group, created = Group.objects.get_or_create(name="Scuba Divers") + bw_group, created = Group.objects.get_or_create(name="Basket Weavers") # Put user1 and user2 in one group, user3 and user4 in another - usernames = ['user1', 'user2', 'user3', 'user4', 'staffer'] + usernames = ["user1", "user2", "user3", "user4", "staffer"] for username in usernames: if get_user_model().objects.filter(username=username).exists(): user = get_user_model().objects.get(username=username) @@ -70,15 +71,16 @@ class Command(BaseCommand): first_name=fake.first_name(), last_name=fake.last_name(), email="{}@example.com".format(username), - password="todo") + password="todo", + ) - if username in ['user1', 'user2']: + if username in ["user1", "user2"]: user.groups.add(bw_group) - if username in ['user3', 'user4']: + if username in ["user3", "user4"]: user.groups.add(sd_group) - if username == 'staffer': + if username == "staffer": user.is_staff = True user.first_name = fake.first_name() user.last_name = fake.last_name() @@ -91,7 +93,9 @@ class Command(BaseCommand): TaskListFactory.create_batch(5, group=sd_group) TaskListFactory.create(name="Public Tickets", slug="tickets", group=bw_group) - print("For each of two groups, created fake tasks in each of {} fake lists.".format(num_lists)) + print( + "For each of two groups, created fake tasks in each of {} fake lists.".format(num_lists) + ) class TaskListFactory(factory.django.DjangoModelFactory): @@ -120,9 +124,11 @@ class TaskFactory(factory.django.DjangoModelFactory): task_list = None # Pass this in note = factory.LazyAttribute(lambda o: gen_content()) priority = factory.LazyAttribute(lambda o: random.randint(1, 100)) - completed = factory.Faker('boolean', chance_of_getting_true=30) - created_by = factory.LazyAttribute(lambda o: get_user_model().objects.get(username='staffer')) # Randomized in post - created_date = factory.Faker('date_this_year') + completed = factory.Faker("boolean", chance_of_getting_true=30) + created_by = factory.LazyAttribute( + lambda o: get_user_model().objects.get(username="staffer") + ) # Randomized in post + created_date = factory.Faker("date_this_year") @factory.post_generation def add_details(self, build, extracted, **kwargs): @@ -130,7 +136,7 @@ class TaskFactory(factory.django.DjangoModelFactory): fake = Faker() # Use to create user's names taskgroup = self.task_list.group - self.created_by = taskgroup.user_set.all().order_by('?').first() + self.created_by = taskgroup.user_set.all().order_by("?").first() if self.completed: self.completed_date = fake.date_this_year() @@ -141,6 +147,6 @@ class TaskFactory(factory.django.DjangoModelFactory): # 1/3 of generated tasks are assigned to someone in this tasks's group if random.randint(1, 3) == 1: - self.assigned_to = taskgroup.user_set.all().order_by('?').first() + self.assigned_to = taskgroup.user_set.all().order_by("?").first() self.save() diff --git a/todo/management/commands/mail_worker.py b/todo/management/commands/mail_worker.py index b0750fd..717e7f9 100644 --- a/todo/management/commands/mail_worker.py +++ b/todo/management/commands/mail_worker.py @@ -26,10 +26,7 @@ class Command(BaseCommand): worker_name = options["worker_name"] tracker = settings.TODO_MAIL_TRACKERS.get(worker_name, None) if tracker is None: - logger.error( - "couldn't find configuration for %r in TODO_MAIL_TRACKERS", - worker_name - ) + logger.error("couldn't find configuration for %r in TODO_MAIL_TRACKERS", worker_name) sys.exit(1) # set the default socket timeout (imaplib doesn't enable configuring it) diff --git a/todo/migrations/0001_initial.py b/todo/migrations/0001_initial.py index c29c7a6..7b0fff1 100644 --- a/todo/migrations/0001_initial.py +++ b/todo/migrations/0001_initial.py @@ -9,70 +9,93 @@ from django.conf import settings class Migration(migrations.Migration): dependencies = [ - ('auth', '0001_initial'), + ("auth", "0001_initial"), migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ migrations.CreateModel( - name='Comment', + name="Comment", fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('date', models.DateTimeField(default=datetime.datetime.now)), - ('body', models.TextField(blank=True)), - ('author', models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)), + ( + "id", + models.AutoField( + verbose_name="ID", serialize=False, auto_created=True, primary_key=True + ), + ), + ("date", models.DateTimeField(default=datetime.datetime.now)), + ("body", models.TextField(blank=True)), + ( + "author", + models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE), + ), ], - options={ - }, + options={}, bases=(models.Model,), ), migrations.CreateModel( - name='Item', + name="Item", fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('title', models.CharField(max_length=140)), - ('created_date', models.DateField(auto_now=True, auto_now_add=True)), - ('due_date', models.DateField(null=True, blank=True)), - ('completed', models.BooleanField(default=None)), - ('completed_date', models.DateField(null=True, blank=True)), - ('note', models.TextField(null=True, blank=True)), - ('priority', models.PositiveIntegerField(max_length=3)), - ('assigned_to', models.ForeignKey(related_name='todo_assigned_to', to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)), - ('created_by', models.ForeignKey(related_name='todo_created_by', to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)), + ( + "id", + models.AutoField( + verbose_name="ID", serialize=False, auto_created=True, primary_key=True + ), + ), + ("title", models.CharField(max_length=140)), + ("created_date", models.DateField(auto_now=True, auto_now_add=True)), + ("due_date", models.DateField(null=True, blank=True)), + ("completed", models.BooleanField(default=None)), + ("completed_date", models.DateField(null=True, blank=True)), + ("note", models.TextField(null=True, blank=True)), + ("priority", models.PositiveIntegerField(max_length=3)), + ( + "assigned_to", + models.ForeignKey( + related_name="todo_assigned_to", + to=settings.AUTH_USER_MODEL, + on_delete=models.CASCADE, + ), + ), + ( + "created_by", + models.ForeignKey( + related_name="todo_created_by", + to=settings.AUTH_USER_MODEL, + on_delete=models.CASCADE, + ), + ), ], - options={ - 'ordering': ['priority'], - }, + options={"ordering": ["priority"]}, bases=(models.Model,), ), migrations.CreateModel( - name='List', + name="List", fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('name', models.CharField(max_length=60)), - ('slug', models.SlugField(max_length=60, editable=False)), - ('group', models.ForeignKey(to='auth.Group', on_delete=models.CASCADE)), + ( + "id", + models.AutoField( + verbose_name="ID", serialize=False, auto_created=True, primary_key=True + ), + ), + ("name", models.CharField(max_length=60)), + ("slug", models.SlugField(max_length=60, editable=False)), + ("group", models.ForeignKey(to="auth.Group", on_delete=models.CASCADE)), ], - options={ - 'ordering': ['name'], - 'verbose_name_plural': 'Lists', - }, + options={"ordering": ["name"], "verbose_name_plural": "Lists"}, bases=(models.Model,), ), - migrations.AlterUniqueTogether( - name='list', - unique_together=set([('group', 'slug')]), - ), + migrations.AlterUniqueTogether(name="list", unique_together=set([("group", "slug")])), migrations.AddField( - model_name='item', - name='list', - field=models.ForeignKey(to='todo.List', on_delete=models.CASCADE), + model_name="item", + name="list", + field=models.ForeignKey(to="todo.List", on_delete=models.CASCADE), preserve_default=True, ), migrations.AddField( - model_name='comment', - name='task', - field=models.ForeignKey(to='todo.Item', on_delete=models.CASCADE), + model_name="comment", + name="task", + field=models.ForeignKey(to="todo.Item", on_delete=models.CASCADE), preserve_default=True, ), ] diff --git a/todo/migrations/0002_auto_20150614_2339.py b/todo/migrations/0002_auto_20150614_2339.py index a346e88..09f2d4a 100644 --- a/todo/migrations/0002_auto_20150614_2339.py +++ b/todo/migrations/0002_auto_20150614_2339.py @@ -6,19 +6,13 @@ from django.db import models, migrations class Migration(migrations.Migration): - dependencies = [ - ('todo', '0001_initial'), - ] + dependencies = [("todo", "0001_initial")] operations = [ migrations.AlterField( - model_name='item', - name='created_date', - field=models.DateField(auto_now=True), + model_name="item", name="created_date", field=models.DateField(auto_now=True) ), migrations.AlterField( - model_name='item', - name='priority', - field=models.PositiveIntegerField(), + model_name="item", name="priority", field=models.PositiveIntegerField() ), ] diff --git a/todo/migrations/0003_assignee_optional.py b/todo/migrations/0003_assignee_optional.py index f5f2625..e370ea0 100644 --- a/todo/migrations/0003_assignee_optional.py +++ b/todo/migrations/0003_assignee_optional.py @@ -9,14 +9,18 @@ import django.db.models.deletion class Migration(migrations.Migration): - dependencies = [ - ('todo', '0002_auto_20150614_2339'), - ] + dependencies = [("todo", "0002_auto_20150614_2339")] operations = [ migrations.AlterField( - model_name='item', - name='assigned_to', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='todo_assigned_to', to=settings.AUTH_USER_MODEL), - ), + model_name="item", + name="assigned_to", + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="todo_assigned_to", + to=settings.AUTH_USER_MODEL, + ), + ) ] diff --git a/todo/migrations/0004_rename_list_tasklist.py b/todo/migrations/0004_rename_list_tasklist.py index 65e9b04..41f5fee 100644 --- a/todo/migrations/0004_rename_list_tasklist.py +++ b/todo/migrations/0004_rename_list_tasklist.py @@ -7,46 +7,39 @@ import django.db.models.deletion class Migration(migrations.Migration): dependencies = [ - ('auth', '0009_alter_user_last_name_max_length'), - ('todo', '0003_assignee_optional'), + ("auth", "0009_alter_user_last_name_max_length"), + ("todo", "0003_assignee_optional"), ] operations = [ migrations.CreateModel( - name='TaskList', + name="TaskList", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=60)), - ('slug', models.SlugField(default='')), - ('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='auth.Group')), + ( + "id", + models.AutoField( + auto_created=True, primary_key=True, serialize=False, verbose_name="ID" + ), + ), + ("name", models.CharField(max_length=60)), + ("slug", models.SlugField(default="")), + ( + "group", + models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to="auth.Group"), + ), ], - options={ - 'verbose_name_plural': 'Lists', - 'ordering': ['name'], - }, - ), - migrations.AlterUniqueTogether( - name='list', - unique_together=set(), - ), - migrations.RemoveField( - model_name='list', - name='group', - ), - migrations.RemoveField( - model_name='item', - name='list', - ), - migrations.DeleteModel( - name='List', + options={"verbose_name_plural": "Lists", "ordering": ["name"]}, ), + migrations.AlterUniqueTogether(name="list", unique_together=set()), + migrations.RemoveField(model_name="list", name="group"), + migrations.RemoveField(model_name="item", name="list"), + migrations.DeleteModel(name="List"), migrations.AddField( - model_name='item', - name='task_list', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='todo.TaskList'), - ), - migrations.AlterUniqueTogether( - name='tasklist', - unique_together={('group', 'slug')}, + model_name="item", + name="task_list", + field=models.ForeignKey( + null=True, on_delete=django.db.models.deletion.CASCADE, to="todo.TaskList" + ), ), + migrations.AlterUniqueTogether(name="tasklist", unique_together={("group", "slug")}), ] diff --git a/todo/migrations/0005_auto_20180212_2325.py b/todo/migrations/0005_auto_20180212_2325.py index 5a8c466..94a2c9c 100644 --- a/todo/migrations/0005_auto_20180212_2325.py +++ b/todo/migrations/0005_auto_20180212_2325.py @@ -5,18 +5,13 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ - ('todo', '0004_rename_list_tasklist'), - ] + dependencies = [("todo", "0004_rename_list_tasklist")] operations = [ migrations.AlterModelOptions( - name='tasklist', - options={'ordering': ['name'], 'verbose_name_plural': 'Task Lists'}, + name="tasklist", options={"ordering": ["name"], "verbose_name_plural": "Task Lists"} ), migrations.AlterField( - model_name='item', - name='completed', - field=models.BooleanField(default=False), + model_name="item", name="completed", field=models.BooleanField(default=False) ), ] diff --git a/todo/migrations/0006_rename_item_model.py b/todo/migrations/0006_rename_item_model.py index cd9830d..42f5c51 100644 --- a/todo/migrations/0006_rename_item_model.py +++ b/todo/migrations/0006_rename_item_model.py @@ -8,12 +8,7 @@ class Migration(migrations.Migration): atomic = False dependencies = [ migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('todo', '0005_auto_20180212_2325'), + ("todo", "0005_auto_20180212_2325"), ] - operations = [ - migrations.RenameModel( - old_name='Item', - new_name='Task', - ), - ] + operations = [migrations.RenameModel(old_name="Item", new_name="Task")] diff --git a/todo/migrations/0007_auto_update_created_date.py b/todo/migrations/0007_auto_update_created_date.py index dfee145..b98eb94 100644 --- a/todo/migrations/0007_auto_update_created_date.py +++ b/todo/migrations/0007_auto_update_created_date.py @@ -6,14 +6,12 @@ import django.utils.timezone class Migration(migrations.Migration): - dependencies = [ - ('todo', '0006_rename_item_model'), - ] + dependencies = [("todo", "0006_rename_item_model")] operations = [ migrations.AlterField( - model_name='task', - name='created_date', + model_name="task", + name="created_date", field=models.DateField(blank=True, default=django.utils.timezone.now, null=True), - ), + ) ] diff --git a/todo/migrations/0009_priority_optional.py b/todo/migrations/0009_priority_optional.py index 108ec30..1dd6305 100644 --- a/todo/migrations/0009_priority_optional.py +++ b/todo/migrations/0009_priority_optional.py @@ -5,18 +5,15 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ - ('todo', '0008_mail_tracker'), - ] + dependencies = [("todo", "0008_mail_tracker")] operations = [ migrations.AlterModelOptions( - name='task', - options={'ordering': ['priority', 'created_date']}, + name="task", options={"ordering": ["priority", "created_date"]} ), migrations.AlterField( - model_name='task', - name='priority', + model_name="task", + name="priority", field=models.PositiveIntegerField(blank=True, null=True), ), ] diff --git a/todo/migrations/0010_attachment.py b/todo/migrations/0010_attachment.py index 885411a..2f62eff 100644 --- a/todo/migrations/0010_attachment.py +++ b/todo/migrations/0010_attachment.py @@ -11,18 +11,36 @@ class Migration(migrations.Migration): dependencies = [ migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('todo', '0009_priority_optional'), + ("todo", "0009_priority_optional"), ] operations = [ migrations.CreateModel( - name='Attachment', + name="Attachment", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('timestamp', models.DateTimeField(default=datetime.datetime.now)), - ('file', models.FileField(max_length=255, upload_to=todo.models.get_attachment_upload_dir)), - ('added_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), - ('task', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='todo.Task')), + ( + "id", + models.AutoField( + auto_created=True, primary_key=True, serialize=False, verbose_name="ID" + ), + ), + ("timestamp", models.DateTimeField(default=datetime.datetime.now)), + ( + "file", + models.FileField( + max_length=255, upload_to=todo.models.get_attachment_upload_dir + ), + ), + ( + "added_by", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL + ), + ), + ( + "task", + models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to="todo.Task"), + ), ], - ), + ) ] diff --git a/todo/models.py b/todo/models.py index a9582dc..60ab220 100644 --- a/todo/models.py +++ b/todo/models.py @@ -45,9 +45,7 @@ class LockedAtomicTransaction(Atomic): cursor = get_connection(self.using).cursor() for model in self.models: cursor.execute( - "LOCK TABLE {table_name}".format( - table_name=model._meta.db_table - ) + "LOCK TABLE {table_name}".format(table_name=model._meta.db_table) ) finally: if cursor and not cursor.closed: @@ -159,9 +157,7 @@ class Comment(models.Model): def snippet(self): body_snippet = textwrap.shorten(self.body, width=35, placeholder="...") # Define here rather than in __str__ so we can use it in the admin list_display - return "{author} - {snippet}...".format( - author=self.author_text, snippet=body_snippet - ) + return "{author} - {snippet}...".format(author=self.author_text, snippet=body_snippet) def __str__(self): return self.snippet @@ -173,9 +169,7 @@ class Attachment(models.Model): """ task = models.ForeignKey(Task, on_delete=models.CASCADE) - added_by = models.ForeignKey( - settings.AUTH_USER_MODEL, on_delete=models.CASCADE - ) + added_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) timestamp = models.DateTimeField(default=datetime.datetime.now) file = models.FileField(upload_to=get_attachment_upload_dir, max_length=255) diff --git a/todo/operations/csv_importer.py b/todo/operations/csv_importer.py index 7b847fa..6313786 100644 --- a/todo/operations/csv_importer.py +++ b/todo/operations/csv_importer.py @@ -67,7 +67,11 @@ class CSVImporter: # newrow at this point is fully validated, and all FK relations exist, # e.g. `newrow.get("Assigned To")`, is a Django User instance. assignee = newrow.get("Assigned To") if newrow.get("Assigned To") else None - created_date = newrow.get("Created Date") if newrow.get("Created Date") else datetime.datetime.today() + created_date = ( + newrow.get("Created Date") + if newrow.get("Created Date") + else datetime.datetime.today() + ) due_date = newrow.get("Due Date") if newrow.get("Due Date") else None priority = newrow.get("Priority") if newrow.get("Priority") else None @@ -178,7 +182,7 @@ class CSVImporter: row["Assigned To"] = assignee # Set Completed - row["Completed"] = (row["Completed"] == "Yes") + row["Completed"] = row["Completed"] == "Yes" # ####################### if row_errors: diff --git a/todo/tests/test_tracker.py b/todo/tests/test_tracker.py index 3387d75..5ea5ad0 100644 --- a/todo/tests/test_tracker.py +++ b/todo/tests/test_tracker.py @@ -9,24 +9,21 @@ from email.message import EmailMessage def consumer(*args, title_format="[TEST] {subject}", **kwargs): return tracker_consumer( - group="Workgroup One", - task_list_slug="zip", - priority=1, - task_title_format=title_format, + group="Workgroup One", task_list_slug="zip", priority=1, task_title_format=title_format )(*args, **kwargs) def make_message(subject, content): msg = EmailMessage() msg.set_content(content) - msg['Subject'] = subject + msg["Subject"] = subject return msg def test_tracker_task_creation(todo_setup, django_user_model): msg = make_message("test1 subject", "test1 content") - msg['From'] = 'test1@example.com' - msg['Message-ID'] = '' + msg["From"] = "test1@example.com" + msg["Message-ID"] = "" # test task creation task_count = Task.objects.count() @@ -38,30 +35,26 @@ def test_tracker_task_creation(todo_setup, django_user_model): # test thread answers msg = make_message("test2 subject", "test2 content") - msg['From'] = 'test1@example.com' - msg['Message-ID'] = '' - msg['References'] = ' ' + msg["From"] = "test1@example.com" + msg["Message-ID"] = "" + msg["References"] = " " task_count = Task.objects.count() consumer([msg]) assert task_count == Task.objects.count(), "comment created another task" Comment.objects.get( - task=task, - body__contains="test2 content", - email_message_id='' + task=task, body__contains="test2 content", email_message_id="" ) # test notification answer msg = make_message("test3 subject", "test3 content") - msg['From'] = 'test1@example.com' - msg['Message-ID'] = '' - msg['References'] = ' '.format(task.pk) + msg["From"] = "test1@example.com" + msg["Message-ID"] = "" + msg["References"] = " ".format(task.pk) task_count = Task.objects.count() consumer([msg]) assert task_count == Task.objects.count(), "comment created another task" Comment.objects.get( - task=task, - body__contains="test3 content", - email_message_id='' + task=task, body__contains="test3 content", email_message_id="" ) diff --git a/todo/tests/test_utils.py b/todo/tests/test_utils.py index 48f3149..cf26a38 100644 --- a/todo/tests/test_utils.py +++ b/todo/tests/test_utils.py @@ -55,5 +55,6 @@ def test_send_email_to_thread_participants(todo_setup, django_user_model, email_ assert "u3@example.com" in mail.outbox[0].recipients() assert "u4@example.com" in mail.outbox[0].recipients() + # FIXME: Add tests for: -# Attachments: Test whether allowed, test multiple, test extensions \ No newline at end of file +# Attachments: Test whether allowed, test multiple, test extensions diff --git a/todo/tests/test_views.py b/todo/tests/test_views.py index c15d9df..9ad05d6 100644 --- a/todo/tests/test_views.py +++ b/todo/tests/test_views.py @@ -166,6 +166,7 @@ def test_no_javascript_in_comments(todo_setup, client): # ### PERMISSIONS ### + def test_view_add_list_nonadmin(todo_setup, client): url = reverse("todo:add_list") client.login(username="you", password="password") diff --git a/todo/urls.py b/todo/urls.py index a539616..9b68ca2 100644 --- a/todo/urls.py +++ b/todo/urls.py @@ -4,93 +4,46 @@ from django.urls import path from todo import views from todo.features import HAS_TASK_MERGE -app_name = 'todo' +app_name = "todo" urlpatterns = [ - path( - '', - views.list_lists, - name="lists"), - + path("", views.list_lists, name="lists"), # View reorder_tasks is only called by JQuery for drag/drop task ordering. - path( - 'reorder_tasks/', - views.reorder_tasks, - name="reorder_tasks"), - + path("reorder_tasks/", views.reorder_tasks, name="reorder_tasks"), # Allow users to post tasks from outside django-todo (e.g. for filing tickets - see docs) - path( - 'ticket/add/', - views.external_add, - name="external_add"), - + path("ticket/add/", views.external_add, name="external_add"), # Three paths into `list_detail` view + path("mine/", views.list_detail, {"list_slug": "mine"}, name="mine"), path( - 'mine/', + "//completed/", views.list_detail, - {'list_slug': 'mine'}, - name="mine"), - + {"view_completed": True}, + name="list_detail_completed", + ), + path("//", views.list_detail, name="list_detail"), + path("//delete/", views.del_list, name="del_list"), + path("add_list/", views.add_list, name="add_list"), + path("task//", views.task_detail, name="task_detail"), path( - '//completed/', - views.list_detail, - {'view_completed': True}, - name='list_detail_completed'), - - path( - '//', - views.list_detail, - name='list_detail'), - - path( - '//delete/', - views.del_list, - name="del_list"), - - path( - 'add_list/', - views.add_list, - name="add_list"), - - path( - 'task//', - views.task_detail, - name='task_detail'), - - path( - 'attachment/remove//', - views.remove_attachment, - name='remove_attachment'), + "attachment/remove//", views.remove_attachment, name="remove_attachment" + ), ] if HAS_TASK_MERGE: # ensure mail tracker autocomplete is optional from todo.views.task_autocomplete import TaskAutocomplete + urlpatterns.append( path( - 'task//autocomplete/', - TaskAutocomplete.as_view(), - name='task_autocomplete') + "task//autocomplete/", TaskAutocomplete.as_view(), name="task_autocomplete" + ) ) -urlpatterns.extend([ - path( - 'toggle_done//', - views.toggle_done, - name='task_toggle_done'), - - path( - 'delete//', - views.delete_task, - name='delete_task'), - - path( - 'search/', - views.search, - name="search"), - - path( - 'import_csv/', - views.import_csv, - name="import_csv"), -]) +urlpatterns.extend( + [ + path("toggle_done//", views.toggle_done, name="task_toggle_done"), + path("delete//", views.delete_task, name="delete_task"), + path("search/", views.search, name="search"), + path("import_csv/", views.import_csv, name="import_csv"), + ] +) diff --git a/todo/utils.py b/todo/utils.py index f63df38..a2b6fa8 100644 --- a/todo/utils.py +++ b/todo/utils.py @@ -20,7 +20,7 @@ def staff_check(user): https://github.com/shacker/django-todo/issues/50 """ - if defaults('TODO_STAFF_ONLY'): + if defaults("TODO_STAFF_ONLY"): return user.is_staff else: # If unset or False, allow all logged in users diff --git a/todo/views/external_add.py b/todo/views/external_add.py index f5f7950..077b527 100644 --- a/todo/views/external_add.py +++ b/todo/views/external_add.py @@ -43,7 +43,7 @@ def external_add(request) -> HttpResponse: task = form.save(commit=False) task.task_list = TaskList.objects.get(slug=settings.TODO_DEFAULT_LIST_SLUG) task.created_by = request.user - if defaults('TODO_DEFAULT_ASSIGNEE'): + if defaults("TODO_DEFAULT_ASSIGNEE"): task.assigned_to = User.objects.get(username=settings.TODO_DEFAULT_ASSIGNEE) task.save() diff --git a/todo/views/remove_attachment.py b/todo/views/remove_attachment.py index 75b235f..588e31e 100644 --- a/todo/views/remove_attachment.py +++ b/todo/views/remove_attachment.py @@ -18,10 +18,7 @@ def remove_attachment(request, attachment_id: int) -> HttpResponse: if request.method == "POST": attachment = get_object_or_404(Attachment, pk=attachment_id) - redir_url = reverse( - "todo:task_detail", - kwargs={"task_id": attachment.task.id}, - ) + redir_url = reverse("todo:task_detail", kwargs={"task_id": attachment.task.id}) # Permissions if not ( @@ -33,7 +30,9 @@ def remove_attachment(request, attachment_id: int) -> HttpResponse: if remove_attachment_file(attachment.id): messages.success(request, f"Attachment {attachment.id} removed.") else: - messages.error(request, f"Sorry, there was a problem deleting attachment {attachment.id}.") + messages.error( + request, f"Sorry, there was a problem deleting attachment {attachment.id}." + ) return redirect(redir_url) diff --git a/todo/views/task_detail.py b/todo/views/task_detail.py index fa0f4f3..bf558d4 100644 --- a/todo/views/task_detail.py +++ b/todo/views/task_detail.py @@ -121,13 +121,13 @@ def task_detail(request, task_id: int) -> HttpResponse: if request.FILES.get("attachment_file_input"): file = request.FILES.get("attachment_file_input") - if file.size > defaults('TODO_MAXIMUM_ATTACHMENT_SIZE'): + if file.size > defaults("TODO_MAXIMUM_ATTACHMENT_SIZE"): messages.error(request, f"File exceeds maximum attachment size.") return redirect("todo:task_detail", task_id=task.id) name, extension = os.path.splitext(file.name) - if extension not in defaults('TODO_LIMIT_FILE_ATTACHMENTS'): + if extension not in defaults("TODO_LIMIT_FILE_ATTACHMENTS"): messages.error(request, f"This site does not allow upload of {extension} files.") return redirect("todo:task_detail", task_id=task.id) @@ -144,7 +144,7 @@ def task_detail(request, task_id: int) -> HttpResponse: "merge_form": merge_form, "thedate": thedate, "comment_classes": defaults("TODO_COMMENT_CLASSES"), - "attachments_enabled": defaults('TODO_ALLOW_FILE_ATTACHMENTS'), + "attachments_enabled": defaults("TODO_ALLOW_FILE_ATTACHMENTS"), } return render(request, "todo/task_detail.html", context)