Merge remote-tracking branch 'upstream/dev' into feature/unsaved-changes

This commit is contained in:
Michael Shamoon
2021-01-25 23:16:18 -08:00
parent 0a8771829e
commit 09d6d25074
20 changed files with 198 additions and 177 deletions

View File

@@ -70,31 +70,6 @@ def _consume(filepath):
"Error while consuming document: {}".format(e))
def _test_inotify(directory):
if not INotify:
return False
test_file = os.path.join(directory, "__inotify_test_file__")
inotify = INotify()
descriptor = None
try:
inotify_flags = flags.CLOSE_WRITE | flags.MOVED_TO
descriptor = inotify.add_watch(directory, inotify_flags)
Path(test_file).touch()
events = inotify.read(timeout=1000)
return len(events) == 1
except Exception as e:
logger.warning(
f"Error while checking inotify availability: {str(e)}")
return False
finally:
if descriptor:
inotify.rm_watch(descriptor)
inotify.close()
if os.path.isfile(test_file):
os.unlink(test_file)
def _consume_wait_unmodified(file, num_tries=20, wait_time=1):
mtime = -1
current_try = 0
@@ -178,25 +153,17 @@ class Command(BaseCommand):
if options["oneshot"]:
return
if settings.CONSUMER_POLLING == 0:
if _test_inotify(directory):
self.handle_inotify(directory, recursive)
else:
logger.warning(
f"Inotify notifications are not available on {directory}, "
f"falling back to polling every 10 seconds")
self.handle_polling(
directory, recursive, 10)
if settings.CONSUMER_POLLING == 0 and INotify:
self.handle_inotify(directory, recursive)
else:
self.handle_polling(
directory, recursive, settings.CONSUMER_POLLING)
self.handle_polling(directory, recursive)
logger.debug("Consumer exiting.")
def handle_polling(self, directory, recursive, timeout):
def handle_polling(self, directory, recursive):
logging.getLogger(__name__).info(
f"Polling directory for changes: {directory}")
self.observer = PollingObserver(timeout=timeout)
self.observer = PollingObserver(timeout=settings.CONSUMER_POLLING)
self.observer.schedule(Handler(), directory, recursive=recursive)
self.observer.start()
try:

View File

@@ -63,12 +63,6 @@ class MatchingModel(models.Model):
def __str__(self):
return self.name
def save(self, *args, **kwargs):
self.match = self.match.lower()
models.Model.save(self, *args, **kwargs)
class Correspondent(MatchingModel):

View File

@@ -228,6 +228,12 @@ class TestDocumentApi(DirectoriesMixin, APITestCase):
self.assertEqual(len(results), 2)
self.assertCountEqual([results[0]['id'], results[1]['id']], [doc1.id, doc3.id])
response = self.client.get("/api/documents/?tags__id__in={},{}".format(tag_2.id, tag_3.id))
self.assertEqual(response.status_code, 200)
results = response.data['results']
self.assertEqual(len(results), 2)
self.assertCountEqual([results[0]['id'], results[1]['id']], [doc2.id, doc3.id])
response = self.client.get("/api/documents/?tags__id__all={},{}".format(tag_2.id, tag_3.id))
self.assertEqual(response.status_code, 200)
results = response.data['results']
@@ -923,6 +929,14 @@ class TestBulkEdit(DirectoriesMixin, APITestCase):
doc2 = Document.objects.get(id=self.doc2.id)
self.assertEqual(doc2.correspondent, self.c1)
def test_api_no_correspondent(self):
response = self.client.post("/api/documents/bulk_edit/", json.dumps({
"documents": [self.doc2.id],
"method": "set_correspondent",
"parameters": {}
}), content_type='application/json')
self.assertEqual(response.status_code, 400)
def test_api_invalid_document_type(self):
self.assertEqual(self.doc2.document_type, self.dt1)
response = self.client.post("/api/documents/bulk_edit/", json.dumps({
@@ -935,6 +949,14 @@ class TestBulkEdit(DirectoriesMixin, APITestCase):
doc2 = Document.objects.get(id=self.doc2.id)
self.assertEqual(doc2.document_type, self.dt1)
def test_api_no_document_type(self):
response = self.client.post("/api/documents/bulk_edit/", json.dumps({
"documents": [self.doc2.id],
"method": "set_document_type",
"parameters": {}
}), content_type='application/json')
self.assertEqual(response.status_code, 400)
def test_api_add_invalid_tag(self):
self.assertEqual(list(self.doc2.tags.all()), [self.t1])
response = self.client.post("/api/documents/bulk_edit/", json.dumps({
@@ -946,6 +968,14 @@ class TestBulkEdit(DirectoriesMixin, APITestCase):
self.assertEqual(list(self.doc2.tags.all()), [self.t1])
def test_api_add_tag_no_tag(self):
response = self.client.post("/api/documents/bulk_edit/", json.dumps({
"documents": [self.doc2.id],
"method": "add_tag",
"parameters": {}
}), content_type='application/json')
self.assertEqual(response.status_code, 400)
def test_api_delete_invalid_tag(self):
self.assertEqual(list(self.doc2.tags.all()), [self.t1])
response = self.client.post("/api/documents/bulk_edit/", json.dumps({
@@ -957,6 +987,14 @@ class TestBulkEdit(DirectoriesMixin, APITestCase):
self.assertEqual(list(self.doc2.tags.all()), [self.t1])
def test_api_delete_tag_no_tag(self):
response = self.client.post("/api/documents/bulk_edit/", json.dumps({
"documents": [self.doc2.id],
"method": "remove_tag",
"parameters": {}
}), content_type='application/json')
self.assertEqual(response.status_code, 400)
def test_api_modify_invalid_tags(self):
self.assertEqual(list(self.doc2.tags.all()), [self.t1])
response = self.client.post("/api/documents/bulk_edit/", json.dumps({
@@ -966,6 +1004,21 @@ class TestBulkEdit(DirectoriesMixin, APITestCase):
}), content_type='application/json')
self.assertEqual(response.status_code, 400)
def test_api_modify_tags_no_tags(self):
response = self.client.post("/api/documents/bulk_edit/", json.dumps({
"documents": [self.doc2.id],
"method": "modify_tags",
"parameters": {"remove_tags": [1123123]}
}), content_type='application/json')
self.assertEqual(response.status_code, 400)
response = self.client.post("/api/documents/bulk_edit/", json.dumps({
"documents": [self.doc2.id],
"method": "modify_tags",
"parameters": {'add_tags': [self.t2.id, 1657]}
}), content_type='application/json')
self.assertEqual(response.status_code, 400)
def test_api_selection_data_empty(self):
response = self.client.post("/api/documents/selection_data/", json.dumps({
"documents": []

View File

@@ -7,9 +7,8 @@ from unittest import mock
from django.conf import settings
from django.core.management import call_command, CommandError
from django.test import override_settings, TransactionTestCase, TestCase
from django.test import override_settings, TransactionTestCase
from documents.management.commands.document_consumer import _test_inotify
from documents.models import Tag
from documents.consumer import ConsumerError
from documents.management.commands import document_consumer
@@ -261,27 +260,3 @@ class TestConsumerTags(DirectoriesMixin, ConsumerMixin, TransactionTestCase):
@override_settings(CONSUMER_POLLING=1)
def test_consume_file_with_path_tags_polling(self):
self.test_consume_file_with_path_tags()
class TestInotify(DirectoriesMixin, TestCase):
def test_inotify(self):
self.assertTrue(_test_inotify(self.dirs.consumption_dir))
@mock.patch("documents.management.commands.document_consumer.Path.touch")
def test_inotify_error(self, m):
m.side_effect = OSError("Permission error")
self.assertFalse(_test_inotify(self.dirs.consumption_dir))
@mock.patch("documents.management.commands.document_consumer.Command.handle_polling")
@mock.patch("documents.management.commands.document_consumer.Command.handle_inotify")
@mock.patch("documents.management.commands.document_consumer._test_inotify")
def test_polling_fallback(self, test_inotify, handle_inotify, handle_polling):
test_inotify.return_value = False
cmd = document_consumer.Command()
cmd.handle(directory=settings.CONSUMPTION_DIR, oneshot=False)
test_inotify.assert_called_once()
handle_polling.assert_called_once()
handle_inotify.assert_not_called()

View File

@@ -120,3 +120,4 @@ class TestParserAvailability(TestCase):
self.assertTrue(is_file_ext_supported('.pdf'))
self.assertFalse(is_file_ext_supported('.hsdfh'))
self.assertFalse(is_file_ext_supported(''))

View File

@@ -159,6 +159,9 @@ class DocumentViewSet(RetrieveModelMixin,
"added",
"archive_serial_number")
def get_queryset(self):
return Document.objects.distinct()
def get_serializer(self, *args, **kwargs):
fields_param = self.request.query_params.get('fields', None)
if fields_param: