diff --git a/chcemvediet/apps/anonymization/management/commands/attachment_anonymization.py b/chcemvediet/apps/anonymization/management/commands/attachment_anonymization.py
index ae2f7c921..e83f7f4e0 100644
--- a/chcemvediet/apps/anonymization/management/commands/attachment_anonymization.py
+++ b/chcemvediet/apps/anonymization/management/commands/attachment_anonymization.py
@@ -5,51 +5,59 @@
from django.core.management.base import BaseCommand, CommandError
from poleno.attachments.models import Attachment
+from poleno.utils.misc import squeeze
from chcemvediet.apps.anonymization.models import AttachmentFinalization
from chcemvediet.apps.inforequests.models import Action
class Command(BaseCommand):
- help = u'Creates AttachmentFinalization for the specified Attachment.'
+ args = u'attachment [file]'
+ help = squeeze(u"""
+ Creates anonymization for the specified Attachment. By default, the file path is read
+ from stdin. File path can be explicitly passed as an command argument. Anonymization
+ created this way will be marked as successful. Only one successful anonymization can be
+ assigned to the Attachment.
+ """)
option_list = BaseCommand.option_list + (
- make_option(u'-f', u'--file',
- dest=u'filename',
- help=u'define file path'),
make_option(u'--content_type',
- help=u'define content type of file',
+ help=squeeze(u"""
+ Content type of file, e.g. "application/pdf". Automatically computed if
+ not specified.
+ """)
),
make_option(u'--debug',
default=u'',
- help=u'add debug message'
+ help=u'Debug message to the newly created anonymization. Empty by default.'
),
make_option(u'--force',
action=u'store_true',
- help=u'overwrite an existing successful AttachmentFinalization'
+ help=squeeze(u"""
+ The command refuses to anonymize attachment if a successful
+ anonymization already exists. This flag disables this check. Deletes all
+ existing successful anonymizations and creates new one. Unsuccessful
+ anonymizations will stay unaffected.
+ """)
),
)
- def usage(self, subcommand=None):
- return u'manage.py attachment_anonymization attachment [options] [file]'
-
def handle(self, *args, **options):
- try:
- filename = options[u'filename'] or args[1]
- except IndexError:
- self.stdout.write(u'Usage: {}'.format(self.usage()))
- self.stdout.write(
- u'Try "manage.py attachment_anonymization --help" for more information.')
- return 1
-
+ if not args:
+ raise CommandError(u'attachment_anonymization takes at least 1 argument (0 given).')
+ if len(args) > 2:
+ raise CommandError(
+ u'attachment_anonymization takes at most 2 arguments ({} given).'.format(len(args))
+ )
+ pk = args[0]
+ filename = args[1] if len(args) == 2 else raw_input(u'File:')
+ if not filename:
+ raise CommandError(u'Missing source file name.')
with open(filename, u'rb') as file:
try:
- attachment = (Attachment.objects
- .attached_to(Action)
- .not_normalized()
- .get(pk=int(args[0])))
+ attachment = Attachment.objects.attached_to(Action).get(pk=pk)
attachments_finalization = (AttachmentFinalization.objects
- .filter(attachment=attachment)
- .successful())
+ .filter(attachment=attachment)
+ .successful())
if options[u'force'] or not attachments_finalization:
attachments_finalization.delete()
content = file.read()
@@ -61,5 +69,10 @@ def handle(self, *args, **options):
content_type=options[u'content_type'] or content_type,
debug=options[u'debug'],
)
+ else:
+ raise CommandError(squeeze(u"""
+ Anonymization files already exist. Use the --force option to overwrite
+ them.
+ """))
except Attachment.DoesNotExist:
- raise CommandError(u'Attachment {} does not exist'.format(args[0]))
+ raise CommandError(u'Attachment instance with pk {} does not exist.'.format(pk))
diff --git a/chcemvediet/apps/anonymization/tests/test_management_commands.py b/chcemvediet/apps/anonymization/tests/test_management_commands.py
index 6440b79bf..e8b63bf6e 100644
--- a/chcemvediet/apps/anonymization/tests/test_management_commands.py
+++ b/chcemvediet/apps/anonymization/tests/test_management_commands.py
@@ -1,9 +1,11 @@
import os
+import sys
+from StringIO import StringIO
from testfixtures import TempDirectory
from django.core.management import call_command
+from django.core.management.base import CommandError
from django.test import TestCase
-from django.test.utils import override_settings
from chcemvediet.apps.anonymization.models import AttachmentFinalization
from chcemvediet.tests import ChcemvedietTestCaseMixin
@@ -14,14 +16,11 @@ class AttachmentAnonymizationManagementCommandTest(ChcemvedietTestCaseMixin, Tes
def _pre_setup(self):
super(AttachmentAnonymizationManagementCommandTest, self)._pre_setup()
self.tempdir = TempDirectory()
- self.settings_override = override_settings(
- MEDIA_ROOT=self.tempdir.path,
- )
- self.settings_override.enable()
+ self.tempdir.write(u'testfile.txt', u'Default testing content')
+ self.filename = os.path.join(self.tempdir.path, u'testfile.txt')
self.attachment = self._create_attachment()
def _post_teardown(self):
- self.settings_override.disable()
self.tempdir.cleanup()
super(AttachmentAnonymizationManagementCommandTest, self)._post_teardown()
@@ -32,40 +31,66 @@ def _create_attachment(self, **kwargs):
)
- def test_attachment_anonymization_command_with_valid_arguments_creates_attachment_finalization(self):
- with open(os.path.join(self.tempdir.path, u'myfile.txt'), u'w') as file:
- call_command(u'attachment_anonymization', self.attachment.pk, file.name)
- AttachmentFinalization.objects.get(attachment=self.attachment)
-
- def test_attachment_anonymization_command_file_option(self):
- with open(os.path.join(self.tempdir.path, u'myfile.txt'), u'w') as file:
- call_command(u'attachment_anonymization', self.attachment.pk, filename=file.name)
- AttachmentFinalization.objects.get(attachment=self.attachment)
-
- def test_attachment_anonymization_command_content_type_option(self):
- with open(os.path.join(self.tempdir.path, u'myfile.txt'), u'w') as file:
- call_command(u'attachment_anonymization', self.attachment.pk, file.name, content_type=u'type')
- attachment_finalization = AttachmentFinalization.objects.get(attachment=self.attachment)
- self.assertEqual(attachment_finalization.content_type, u'type')
-
- def test_attachment_anonymization_command_debug_option(self):
- with open(os.path.join(self.tempdir.path, u'myfile.txt'), u'w') as file:
- call_command(u'attachment_anonymization', self.attachment.pk, file.name, debug=u'debug')
- attachment_finalization = AttachmentFinalization.objects.get(attachment=self.attachment)
- self.assertEqual(attachment_finalization.debug, u'debug')
-
- def test_attachment_anonymization_command_with_existing_attachment_finalization(self):
- with open(os.path.join(self.tempdir.path, u'myfile.txt'), u'w') as file:
- call_command(u'attachment_anonymization', self.attachment.pk, file.name)
- attachment_finalization1 = AttachmentFinalization.objects.get(attachment=self.attachment)
- call_command(u'attachment_anonymization', self.attachment.pk, file.name)
- attachment_finalization2 = AttachmentFinalization.objects.get(attachment=self.attachment)
- self.assertEqual(attachment_finalization1.pk, attachment_finalization2.pk)
-
- def test_attachment_anonymization_command_force_option(self):
- with open(os.path.join(self.tempdir.path, u'myfile.txt'), u'w') as file:
- call_command(u'attachment_anonymization', self.attachment.pk, file.name)
- attachment_finalization1 = AttachmentFinalization.objects.get(attachment=self.attachment)
- call_command(u'attachment_anonymization', self.attachment.pk, file.name, force=True)
- attachment_finalization2 = AttachmentFinalization.objects.get(attachment=self.attachment)
- self.assertNotEqual(attachment_finalization1.pk, attachment_finalization2.pk)
+ def test_attachment_and_file_arguments(self):
+ call_command(u'attachment_anonymization', self.attachment.pk, self.filename)
+ attachment_finalization = AttachmentFinalization.objects.get(attachment=self.attachment)
+ self.assertEqual(attachment_finalization.attachment.pk, self.attachment.pk)
+ self.assertEqual(attachment_finalization.file.read(), u'Default testing content')
+ self.assertEqual(attachment_finalization.successful, True)
+
+ def test_attachment_argument_may_not_be_omitted(self):
+ with self.assertRaisesMessage(CommandError, u'attachment_anonymization takes at least 1 argument (0 given).'):
+ call_command(u'attachment_anonymization')
+
+ def test_non_existent_attachment_raises_exception(self):
+ with self.assertRaisesMessage(CommandError, u'Attachment instance with pk -1 does not exist.'):
+ call_command(u'attachment_anonymization', u'-1', self.filename)
+
+ def test_command_with_too_many_arguments(self):
+ with self.assertRaisesMessage(CommandError, u'attachment_anonymization takes at most 2 arguments (3 given).'):
+ call_command(u'attachment_anonymization', self.attachment.pk, self.filename, u'filename2')
+
+ def test_file_argument_is_read_from_stdin_if_omitted(self):
+ self.addCleanup(setattr, sys, u'stdin', sys.stdin)
+ sys.stdin = StringIO(self.filename)
+ call_command(u'attachment_anonymization', self.attachment.pk)
+
+ def test_file_argument_and_stdin_together_may_not_be_omitted(self):
+ self.addCleanup(setattr, sys, u'stdin', sys.stdin)
+ sys.stdin = StringIO(u'\n')
+ with self.assertRaisesMessage(CommandError, u'Missing source file name.'):
+ call_command(u'attachment_anonymization', self.attachment.pk)
+
+ def test_content_type_option(self):
+ call_command(u'attachment_anonymization', self.attachment.pk, self.filename, content_type=u'application/pdf')
+ attachment_finalization = AttachmentFinalization.objects.get(attachment=self.attachment)
+ self.assertEqual(attachment_finalization.content_type, u'application/pdf')
+
+ def test_content_type_option_default_value_if_omitted(self):
+ call_command(u'attachment_anonymization', self.attachment.pk, self.filename)
+ attachment_finalization = AttachmentFinalization.objects.get(attachment=self.attachment)
+ self.assertEqual(attachment_finalization.content_type, u'text/plain')
+
+ def test_debug_option(self):
+ call_command(u'attachment_anonymization', self.attachment.pk, self.filename, debug=u'debug')
+ attachment_finalization = AttachmentFinalization.objects.get(attachment=self.attachment)
+ self.assertEqual(attachment_finalization.debug, u'debug')
+
+ def test_debug_option_default_value_if_omitted(self):
+ call_command(u'attachment_anonymization', self.attachment.pk, self.filename)
+ attachment_finalization = AttachmentFinalization.objects.get(attachment=self.attachment)
+ self.assertEqual(attachment_finalization.debug, u'')
+
+ def test_force_option(self):
+ call_command(u'attachment_anonymization', self.attachment.pk, self.filename)
+ attachment_finalization1 = AttachmentFinalization.objects.get(attachment=self.attachment)
+ call_command(u'attachment_anonymization', self.attachment.pk, self.filename, force=True)
+ attachment_finalization2 = AttachmentFinalization.objects.get(attachment=self.attachment)
+ with self.assertRaisesMessage(AttachmentFinalization.DoesNotExist, u'AttachmentFinalization matching query does not exist'):
+ AttachmentFinalization.objects.get(pk=attachment_finalization1.pk)
+
+ def test_existent_attachment_finalization_raises_exception_if_force_option_is_omitted(self):
+ call_command(u'attachment_anonymization', self.attachment.pk, self.filename)
+ attachment_finalization = AttachmentFinalization.objects.get(attachment=self.attachment)
+ with self.assertRaisesMessage(CommandError, u'Anonymization files already exist. Use the --force option to overwrite them.'):
+ call_command(u'attachment_anonymization', self.attachment.pk, self.filename)
diff --git a/misc/anonymization.md b/misc/anonymization.md
index 8f110ec4b..174eb894f 100644
--- a/misc/anonymization.md
+++ b/misc/anonymization.md
@@ -91,35 +91,24 @@ Computed Properties:
* `content`: String; May be NULL; May be empty; Read-only.
-*\* Features that are marked ~~strikethrough~~ are not implemented yet.*
+## `attachment_anonymization`
+
+ $ env/bin/python manage.py attachment_anonymization [options] attachment_id [file]
+
+
+Creates AttachmentFinalization instance for the specified Attachment. By default, the file path is
+read from stdin. You can pass file path explicitly as an argument.
+AttachmentFinalization created this way will be marked as successful. Only one successful
+AttachmentFinalization can be assigned to the Attachment.
-## Anonymization
-You can manually anonymize `Attachment` using management command:
-
-```
-manage.py attachment_anonymization attachment [options] [file]
-
-Options:
- -v VERBOSITY, --verbosity=VERBOSITY
- Verbosity level; 0=minimal output, 1=normal output,
- 2=verbose output, 3=very verbose output
- --settings=SETTINGS The Python path to a settings module, e.g.
- "myproject.settings.main". If this isn't provided, the
- DJANGO_SETTINGS_MODULE environment variable will be
- used.
- --pythonpath=PYTHONPATH
- A directory to add to the Python path, e.g.
- "/home/djangoprojects/myproject".
- --traceback Raise on exception
- --no-color Don't colorize the command output.
- -f FILENAME, --file=FILENAME
- define file path
- --content_type=CONTENT_TYPE
- define content type of file
- --debug=DEBUG add debug message
- --force overwrite an existing successful
- AttachmentFinalization
- --version show program's version number and exit
- -h, --help show this help message and exit
-```
+* `--content_type=CONTENT_TYPE`: Content type of file, e.g. "application/pdf". Automatically
+ computed if not specified.
+* `--debug=DEBUG`: Debug message to the newly created instance. Empty by default.
+* `--force`: The command refuses to anonymize attachment if a successful anonymization already
+ exists. This flag disables this check. Deletes all existing successful
+ AttachmentFinalizations and creates new one. Unsuccessful AttachmentFinalizations will
+ stay unaffected.
+
+
+*\* Features that are marked ~~strikethrough~~ are not implemented yet.*