From 113ad144e04a6a05989781afc0ca05906283a5ca Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Mon, 27 Jun 2016 19:19:37 -0400 Subject: [PATCH 01/10] Add test mixins for file descriptor leaks and unclaimed temporary files. GitLab issue #309. --- mayan/apps/common/tests/base.py | 11 ++++++++ mayan/apps/common/tests/mixins.py | 42 +++++++++++++++++++++++++++++++ requirements/testing-base.txt | 2 +- 3 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 mayan/apps/common/tests/base.py create mode 100644 mayan/apps/common/tests/mixins.py diff --git a/mayan/apps/common/tests/base.py b/mayan/apps/common/tests/base.py new file mode 100644 index 0000000000..2070ddad06 --- /dev/null +++ b/mayan/apps/common/tests/base.py @@ -0,0 +1,11 @@ +from __future__ import unicode_literals + +from django.test import TestCase + +from .mixins import FileDescriptorCheckMixin, TempfileCheckMixin + + +class BaseTestCase(FileDescriptorCheckMixin, TempfileCheckMixin, TestCase): + """ + This is the most basic test case class any test in the project should use. + """ diff --git a/mayan/apps/common/tests/mixins.py b/mayan/apps/common/tests/mixins.py new file mode 100644 index 0000000000..3ed0f9638c --- /dev/null +++ b/mayan/apps/common/tests/mixins.py @@ -0,0 +1,42 @@ +import os + +import psutil + +from ..settings import setting_temporary_directory + + +class TempfileCheckMixin(object): + def _get_temporary_entries_count(self): + return len(os.listdir(setting_temporary_directory.value)) + + def setUp(self): + super(TempfileCheckMixin, self).setUp() + self._temporary_items = self._get_temporary_entries_count() + + def tearDown(self): + self.assertEqual( + self._temporary_items, self._get_temporary_entries_count(), + msg='Orphan temporary file. The number of temporary file and ' + 'directories at the start and at the end of the test are not the ' + 'same.' + ) + super(TempfileCheckMixin, self).tearDown() + + +class FileDescriptorCheckMixin(object): + def _get_descriptor_count(self): + process = psutil.Process() + return process.num_fds() + + def setUp(self): + super(FileDescriptorCheckMixin, self).setUp() + self._descriptor_count = self._get_descriptor_count() + + def tearDown(self): + self.assertEqual( + self._descriptor_count, self._get_descriptor_count(), + msg='File descriptor leak. The number of file descriptors at ' + 'the start and at the end of the test are not the same.' + ) + super(FileDescriptorCheckMixin, self).tearDown() + diff --git a/requirements/testing-base.txt b/requirements/testing-base.txt index 5b7560fd79..48f9064c42 100644 --- a/requirements/testing-base.txt +++ b/requirements/testing-base.txt @@ -4,4 +4,4 @@ coveralls==0.5 django-test-without-migrations==0.2 mock==2.0.0 tox==2.1.1 - +psutil==4.3.0 From 5ac1276f25bd9dc3376dfc9105ee3b16ba79770b Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Mon, 27 Jun 2016 19:20:42 -0400 Subject: [PATCH 02/10] Add base test class that includes unclaimed temporary and file descriptor test mixins. GitLab issue #309. --- mayan/apps/common/tests/__init__.py | 1 + mayan/apps/common/tests/test_views.py | 15 ++++-------- mayan/apps/django_gpg/tests/test_models.py | 5 ++-- mayan/apps/documents/tests/test_models.py | 28 +++++++++++++++++----- mayan/apps/ocr/tests/test_models.py | 12 +++++++--- mayan/apps/ocr/tests/test_parsers.py | 11 ++++++--- 6 files changed, 46 insertions(+), 26 deletions(-) diff --git a/mayan/apps/common/tests/__init__.py b/mayan/apps/common/tests/__init__.py index e69de29bb2..31efe2d653 100644 --- a/mayan/apps/common/tests/__init__.py +++ b/mayan/apps/common/tests/__init__.py @@ -0,0 +1 @@ +from .base import BaseTestCase # NOQA diff --git a/mayan/apps/common/tests/test_views.py b/mayan/apps/common/tests/test_views.py index fdc2bce50d..9541d06436 100644 --- a/mayan/apps/common/tests/test_views.py +++ b/mayan/apps/common/tests/test_views.py @@ -1,7 +1,5 @@ from __future__ import absolute_import, unicode_literals -import os - from django.conf.urls import url from django.contrib.auth import get_user_model from django.contrib.auth.models import Group @@ -18,15 +16,13 @@ from user_management.tests import ( TEST_USER_EMAIL, TEST_USER_USERNAME, TEST_USER_PASSWORD ) -from ..settings import setting_temporary_directory - +from .base import BaseTestCase from .literals import TEST_VIEW_NAME, TEST_VIEW_URL -class GenericViewTestCase(TestCase): +class GenericViewTestCase(BaseTestCase): def setUp(self): - self.temp_items = len(os.listdir(setting_temporary_directory.value)) - + super(GenericViewTestCase, self).setUp() self.has_test_view = False self.admin_user = get_user_model().objects.create_superuser( username=TEST_ADMIN_USERNAME, email=TEST_ADMIN_EMAIL, @@ -50,10 +46,7 @@ class GenericViewTestCase(TestCase): self.client.logout() if self.has_test_view: urlpatterns.pop(0) - - self.assertEqual( - self.temp_items, len(os.listdir(setting_temporary_directory.value)) - ) + super(GenericViewTestCase, self).tearDown() def add_test_view(self, test_object): from mayan.urls import urlpatterns diff --git a/mayan/apps/django_gpg/tests/test_models.py b/mayan/apps/django_gpg/tests/test_models.py index 019fe4ba7c..f98781ddf5 100644 --- a/mayan/apps/django_gpg/tests/test_models.py +++ b/mayan/apps/django_gpg/tests/test_models.py @@ -5,8 +5,7 @@ import StringIO import gnupg import mock -from django.test import TestCase - +from common.tests import BaseTestCase from common.utils import TemporaryFile from ..exceptions import ( @@ -44,7 +43,7 @@ def mock_recv_keys(self, keyserver, *keyids): return ImportResult() -class KeyTestCase(TestCase): +class KeyTestCase(BaseTestCase): def test_key_instance_creation(self): # Creating a Key instance is analogous to importing a key key = Key.objects.create(key_data=TEST_KEY_DATA) diff --git a/mayan/apps/documents/tests/test_models.py b/mayan/apps/documents/tests/test_models.py index c8ec1d737e..ff9983b656 100644 --- a/mayan/apps/documents/tests/test_models.py +++ b/mayan/apps/documents/tests/test_models.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals from datetime import timedelta import time +from common.tests import BaseTestCase from django.test import TestCase, override_settings from ..exceptions import NewDocumentVersionNotAllowed @@ -16,8 +17,10 @@ from .literals import ( @override_settings(OCR_AUTO_OCR=False) -class DocumentTestCase(TestCase): +class DocumentTestCase(BaseTestCase): def setUp(self): + super(DocumentTestCase, self).setUp() + self.document_type = DocumentType.objects.create( label=TEST_DOCUMENT_TYPE ) @@ -29,6 +32,7 @@ class DocumentTestCase(TestCase): def tearDown(self): self.document_type.delete() + super(DocumentTestCase, self).tearDown() def test_document_creation(self): self.assertEqual(self.document_type.label, TEST_DOCUMENT_TYPE) @@ -135,8 +139,10 @@ class DocumentTestCase(TestCase): @override_settings(OCR_AUTO_OCR=False) -class OfficeDocumentTestCase(TestCase): +class OfficeDocumentTestCase(BaseTestCase): def setUp(self): + super(OfficeDocumentTestCase, self).setUp() + self.document_type = DocumentType.objects.create( label=TEST_DOCUMENT_TYPE ) @@ -148,6 +154,7 @@ class OfficeDocumentTestCase(TestCase): def tearDown(self): self.document_type.delete() + super(OfficeDocumentTestCase, self).tearDown() def test_document_creation(self): self.assertEqual(self.document.file_mimetype, 'application/msword') @@ -162,8 +169,9 @@ class OfficeDocumentTestCase(TestCase): @override_settings(OCR_AUTO_OCR=False) -class MultiPageTiffTestCase(TestCase): +class MultiPageTiffTestCase(BaseTestCase): def setUp(self): + super(MultiPageTiffTestCase, self).setUp() self.document_type = DocumentType.objects.create( label=TEST_DOCUMENT_TYPE ) @@ -175,6 +183,7 @@ class MultiPageTiffTestCase(TestCase): def tearDown(self): self.document_type.delete() + super(MultiPageTiffTestCase, self).tearDown() def test_document_creation(self): self.assertEqual(self.document.file_mimetype, 'image/tiff') @@ -187,8 +196,9 @@ class MultiPageTiffTestCase(TestCase): @override_settings(OCR_AUTO_OCR=False) -class DocumentVersionTestCase(TestCase): +class DocumentVersionTestCase(BaseTestCase): def setUp(self): + super(DocumentVersionTestCase, self).setUp() self.document_type = DocumentType.objects.create( label=TEST_DOCUMENT_TYPE ) @@ -200,6 +210,7 @@ class DocumentVersionTestCase(TestCase): def tearDown(self): self.document_type.delete() + super(DocumentVersionTestCase, self).setUp() def test_add_new_version(self): self.assertEqual(self.document.versions.count(), 1) @@ -236,14 +247,16 @@ class DocumentVersionTestCase(TestCase): @override_settings(OCR_AUTO_OCR=False) -class DocumentManagerTestCase(TestCase): +class DocumentManagerTestCase(BaseTestCase): def setUp(self): + super(DocumentManagerTestCase, self).setUp() self.document_type = DocumentType.objects.create( label=TEST_DOCUMENT_TYPE ) def tearDown(self): self.document_type.delete() + super(DocumentManagerTestCase, self).tearDown() def test_document_stubs_deletion(self): document_stub = Document.objects.create( @@ -265,8 +278,10 @@ class DocumentManagerTestCase(TestCase): @override_settings(OCR_AUTO_OCR=False) -class NewVersionBlockTestCase(TestCase): +class NewVersionBlockTestCase(BaseTestCase): def setUp(self): + super(NewVersionBlockTestCase, self).setUp() + self.document_type = DocumentType.objects.create( label=TEST_DOCUMENT_TYPE ) @@ -279,6 +294,7 @@ class NewVersionBlockTestCase(TestCase): def tearDown(self): self.document.delete() self.document_type.delete() + super(NewVersionBlockTestCase, self).tearDown() def test_blocking(self): NewVersionBlock.objects.block(document=self.document) diff --git a/mayan/apps/ocr/tests/test_models.py b/mayan/apps/ocr/tests/test_models.py index 39daf68e79..d7a834dbd6 100644 --- a/mayan/apps/ocr/tests/test_models.py +++ b/mayan/apps/ocr/tests/test_models.py @@ -3,8 +3,8 @@ from __future__ import unicode_literals from django.core.files.base import File -from django.test import TestCase +from common.tests import BaseTestCase from documents.models import DocumentType from documents.settings import setting_language_choices from documents.tests import ( @@ -12,8 +12,10 @@ from documents.tests import ( ) -class DocumentOCRTestCase(TestCase): +class DocumentOCRTestCase(BaseTestCase): def setUp(self): + super(DocumentOCRTestCase, self).setUp() + self.document_type = DocumentType.objects.create( label=TEST_DOCUMENT_TYPE ) @@ -26,6 +28,7 @@ class DocumentOCRTestCase(TestCase): def tearDown(self): self.document.delete() self.document_type.delete() + super(DocumentOCRTestCase, self).tearDown() def test_ocr_language_backends_end(self): content = self.document.pages.first().ocr_content.content @@ -33,8 +36,10 @@ class DocumentOCRTestCase(TestCase): self.assertTrue('Mayan EDMS Documentation' in content) -class GermanOCRSupportTestCase(TestCase): +class GermanOCRSupportTestCase(BaseTestCase): def setUp(self): + super(GermanOCRSupportTestCase, self).setUp() + self.document_type = DocumentType.objects.create( label=TEST_DOCUMENT_TYPE ) @@ -54,6 +59,7 @@ class GermanOCRSupportTestCase(TestCase): def tearDown(self): self.document_type.delete() + super(GermanOCRSupportTestCase, self).tearDown() def test_ocr_language_backends_end(self): content = self.document.pages.first().ocr_content.content diff --git a/mayan/apps/ocr/tests/test_parsers.py b/mayan/apps/ocr/tests/test_parsers.py index 202f80e70b..a6727c4d0f 100644 --- a/mayan/apps/ocr/tests/test_parsers.py +++ b/mayan/apps/ocr/tests/test_parsers.py @@ -1,9 +1,12 @@ from __future__ import unicode_literals +import psutil + from django.core.files.base import File -from django.test import TestCase, override_settings +from django.test import override_settings from common.settings import setting_temporary_directory +from common.tests import BaseTestCase from documents.models import DocumentType from documents.tests import ( TEST_DOCUMENT_PATH, TEST_DOCUMENT_TYPE, TEST_HYBRID_DOCUMENT_PATH @@ -14,8 +17,9 @@ from ..parsers import PDFMinerParser, PopplerParser @override_settings(OCR_AUTO_OCR=False) -class ParserTestCase(TestCase): +class ParserTestCase(BaseTestCase): def setUp(self): + super(ParserTestCase, self).setUp() self.document_type = DocumentType.objects.create( label=TEST_DOCUMENT_TYPE ) @@ -27,6 +31,7 @@ class ParserTestCase(TestCase): def tearDown(self): self.document_type.delete() + super(ParserTestCase, self).tearDown() def test_pdfminer_parser(self): parser = PDFMinerParser() @@ -48,7 +53,7 @@ class ParserTestCase(TestCase): @override_settings(OCR_AUTO_OCR=False) -class TextExtractorTestCase(TestCase): +class TextExtractorTestCase(BaseTestCase): def setUp(self): self.document_type = DocumentType.objects.create( label=TEST_DOCUMENT_TYPE From d0aee4f72bac9ee320177e7f08a98728a0330e08 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Mon, 27 Jun 2016 19:21:42 -0400 Subject: [PATCH 03/10] Add parameter to fs_cleanup function to close a file descriptor before closing it. GitLab issue #309. --- mayan/apps/common/utils.py | 5 ++++- mayan/apps/ocr/parsers.py | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/mayan/apps/common/utils.py b/mayan/apps/common/utils.py index 56889d2774..1f03bc2e23 100644 --- a/mayan/apps/common/utils.py +++ b/mayan/apps/common/utils.py @@ -45,10 +45,13 @@ def encapsulate(function): return lambda: function -def fs_cleanup(filename, suppress_exceptions=True): +def fs_cleanup(filename, file_descriptor=None, suppress_exceptions=True): """ Tries to remove the given filename. Ignores non-existent files """ + if file_descriptor: + os.close(file_descriptor) + try: os.remove(filename) except OSError: diff --git a/mayan/apps/ocr/parsers.py b/mayan/apps/ocr/parsers.py index 16f8539abd..861f4c212d 100644 --- a/mayan/apps/ocr/parsers.py +++ b/mayan/apps/ocr/parsers.py @@ -155,12 +155,12 @@ class PopplerParser(Parser): return_code = proc.wait() if return_code != 0: logger.error(proc.stderr.readline()) - fs_cleanup(temp_filepath) + fs_cleanup(temp_filepath, file_descriptor=destination_descriptor) raise ParserError output = proc.stdout.read() - fs_cleanup(temp_filepath) + fs_cleanup(temp_filepath, file_descriptor=destination_descriptor) if output == b'\x0c': logger.debug('Parser didn\'t return any output') From f3f5cff36ee156ea0b89557228f87d2f20c74746 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Tue, 28 Jun 2016 01:53:53 -0400 Subject: [PATCH 04/10] Add missing temporary cleanup for the office documents section. --- mayan/apps/converter/classes.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mayan/apps/converter/classes.py b/mayan/apps/converter/classes.py index 69bdf5b6bf..72d3eaf61a 100644 --- a/mayan/apps/converter/classes.py +++ b/mayan/apps/converter/classes.py @@ -167,6 +167,7 @@ class ConverterBase(object): yield data fs_cleanup(input_filepath) + fs_cleanup(converted_output) def get_page(self, output_format=DEFAULT_FILE_FORMAT, as_base64=False): if not self.image: From 2ea3c08c979b2e4f189efbb100fdaa68fe7816e7 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Tue, 28 Jun 2016 03:01:04 -0400 Subject: [PATCH 05/10] Add _future_ import to force unicode. --- mayan/apps/common/tests/mixins.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mayan/apps/common/tests/mixins.py b/mayan/apps/common/tests/mixins.py index 3ed0f9638c..378090f070 100644 --- a/mayan/apps/common/tests/mixins.py +++ b/mayan/apps/common/tests/mixins.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import os import psutil From 063b325986d05f00f3d7c81699af8a7d5e481452 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Tue, 28 Jun 2016 03:01:29 -0400 Subject: [PATCH 06/10] Fix file descriptor leak in document signature download test. --- mayan/apps/document_signatures/tests/test_views.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/mayan/apps/document_signatures/tests/test_views.py b/mayan/apps/document_signatures/tests/test_views.py index adaeebe697..2b0ff6b0f0 100644 --- a/mayan/apps/document_signatures/tests/test_views.py +++ b/mayan/apps/document_signatures/tests/test_views.py @@ -218,9 +218,10 @@ class SignaturesViewTestCase(GenericDocumentViewTestCase): args=(signature.pk,), ) - assert_download_response( - self, response=response, content=signature.signature_file.read(), - ) + with signature.signature_file as file_object: + assert_download_response( + self, response=response, content=file_object.read(), + ) def test_signature_delete_view_no_permission(self): with open(TEST_KEY_FILE) as file_object: From 97089670ee884ae63947cdf5f93078b2191c5612 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Wed, 29 Jun 2016 18:38:46 -0400 Subject: [PATCH 07/10] Change the file descriptor check to use open files instead. Add decorator to skip open file check. GitLab issue #309. --- mayan/apps/common/tests/__init__.py | 1 + mayan/apps/common/tests/base.py | 4 ++-- mayan/apps/common/tests/decorators.py | 5 +++++ mayan/apps/common/tests/mixins.py | 25 +++++++++++++++-------- mayan/apps/documents/tests/test_events.py | 4 ++++ mayan/apps/documents/tests/test_views.py | 14 +++++++++++++ 6 files changed, 42 insertions(+), 11 deletions(-) create mode 100644 mayan/apps/common/tests/decorators.py diff --git a/mayan/apps/common/tests/__init__.py b/mayan/apps/common/tests/__init__.py index 31efe2d653..2da5088d15 100644 --- a/mayan/apps/common/tests/__init__.py +++ b/mayan/apps/common/tests/__init__.py @@ -1 +1,2 @@ from .base import BaseTestCase # NOQA +from .decorators import skip_file_descriptor_check # NOQA diff --git a/mayan/apps/common/tests/base.py b/mayan/apps/common/tests/base.py index 2070ddad06..086179b17b 100644 --- a/mayan/apps/common/tests/base.py +++ b/mayan/apps/common/tests/base.py @@ -2,10 +2,10 @@ from __future__ import unicode_literals from django.test import TestCase -from .mixins import FileDescriptorCheckMixin, TempfileCheckMixin +from .mixins import OpenFileCheckMixin, TempfileCheckMixin -class BaseTestCase(FileDescriptorCheckMixin, TempfileCheckMixin, TestCase): +class BaseTestCase(OpenFileCheckMixin, TempfileCheckMixin, TestCase): """ This is the most basic test case class any test in the project should use. """ diff --git a/mayan/apps/common/tests/decorators.py b/mayan/apps/common/tests/decorators.py new file mode 100644 index 0000000000..9c1b5b8186 --- /dev/null +++ b/mayan/apps/common/tests/decorators.py @@ -0,0 +1,5 @@ +def skip_file_descriptor_check(func): + def func_wrapper(item): + item._skip_file_descriptor_test = True + return func(item) + return func_wrapper diff --git a/mayan/apps/common/tests/mixins.py b/mayan/apps/common/tests/mixins.py index 378090f070..844585ecef 100644 --- a/mayan/apps/common/tests/mixins.py +++ b/mayan/apps/common/tests/mixins.py @@ -25,20 +25,27 @@ class TempfileCheckMixin(object): super(TempfileCheckMixin, self).tearDown() -class FileDescriptorCheckMixin(object): +class OpenFileCheckMixin(object): def _get_descriptor_count(self): process = psutil.Process() return process.num_fds() + def _get_open_files(self): + process = psutil.Process() + return process.open_files() + def setUp(self): - super(FileDescriptorCheckMixin, self).setUp() - self._descriptor_count = self._get_descriptor_count() + super(OpenFileCheckMixin, self).setUp() + self._open_files = self._get_open_files() def tearDown(self): - self.assertEqual( - self._descriptor_count, self._get_descriptor_count(), - msg='File descriptor leak. The number of file descriptors at ' - 'the start and at the end of the test are not the same.' - ) - super(FileDescriptorCheckMixin, self).tearDown() + if not getattr(self, '_skip_file_descriptor_test', False): + for new_open_file in self._get_open_files(): + self.assertFalse(new_open_file not in self._open_files, + msg='File descriptor leak. The number of file descriptors ' + 'at the start and at the end of the test are not the same.' + ) + self._skip_file_descriptor_test = False + + super(OpenFileCheckMixin, self).tearDown() diff --git a/mayan/apps/documents/tests/test_events.py b/mayan/apps/documents/tests/test_events.py index a7e20e6c28..3824de40ee 100644 --- a/mayan/apps/documents/tests/test_events.py +++ b/mayan/apps/documents/tests/test_events.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals from actstream.models import Action +from common.tests import skip_file_descriptor_check from user_management.tests.literals import ( TEST_USER_PASSWORD, TEST_USER_USERNAME ) @@ -38,7 +39,10 @@ class DocumentEventsTestCase(GenericDocumentViewTestCase): self.assertEqual(response.status_code, 302) self.assertEqual(list(Action.objects.any(obj=self.document)), []) + @skip_file_descriptor_check def test_document_download_event_with_permissions(self): + # TODO: Skip this test's file descriptor check until it gets migrate + # SingleObjectDownloadView CBV self.login( username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD ) diff --git a/mayan/apps/documents/tests/test_views.py b/mayan/apps/documents/tests/test_views.py index d952db9aab..3640c67e76 100644 --- a/mayan/apps/documents/tests/test_views.py +++ b/mayan/apps/documents/tests/test_views.py @@ -6,6 +6,7 @@ from django.contrib.contenttypes.models import ContentType from django.test import override_settings from django.utils.six import BytesIO +from common.tests import skip_file_descriptor_check from common.tests.test_views import GenericViewTestCase from converter.models import Transformation from converter.permissions import permission_transformation_delete @@ -225,7 +226,11 @@ class DocumentsViewsTestCase(GenericDocumentViewTestCase): Document.objects.first().document_type, document_type ) + @skip_file_descriptor_check def test_document_download_user_view(self): + # TODO: Skip this test's file descriptor check until it gets migrate + # SingleObjectDownloadView CBV + self.login( username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD ) @@ -257,7 +262,11 @@ class DocumentsViewsTestCase(GenericDocumentViewTestCase): del(buf) + @skip_file_descriptor_check def test_document_multiple_download_user_view(self): + # TODO: Skip this test's file descriptor check until it gets migrate + # SingleObjectDownloadView CBV + self.login( username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD ) @@ -291,7 +300,11 @@ class DocumentsViewsTestCase(GenericDocumentViewTestCase): del(buf) + @skip_file_descriptor_check def test_document_version_download_user_view(self): + # TODO: Skip this test's file descriptor check until it gets migrate + # SingleObjectDownloadView CBV + self.login( username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD ) @@ -358,6 +371,7 @@ class DocumentsViewsTestCase(GenericDocumentViewTestCase): self.assertContains(response, text='queued', status_code=200) self.assertEqual(self.document.pages.count(), page_count) + def test_document_multiple_update_page_count_view_no_permission(self): self.login(username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD) From e62e6a9a08acc442b40bedfc9182539882a9b34b Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Wed, 29 Jun 2016 18:44:51 -0400 Subject: [PATCH 08/10] Remove downloads badge as PyPI downloads tracking is broken and has been marked as "Won't Fix". https://bitbucket.org/pypa/pypi/issues/396/download-stats-have-stopped-working-again --- README.rst | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.rst b/README.rst index 518b9e1ef4..2ba44c413a 100644 --- a/README.rst +++ b/README.rst @@ -1,4 +1,4 @@ -|PyPI badge| |Build Status| |Coverage badge| |Installs badge| |License badge| +|PyPI badge| |Build Status| |Coverage badge| |License badge| |Logo| @@ -63,8 +63,6 @@ Contribute :target: https://gitlab.com/mayan-edms/mayan-edms/commits/master .. |Logo| image:: https://gitlab.com/mayan-edms/mayan-edms/raw/master/docs/_static/mayan_logo.png .. |Animation| image:: https://gitlab.com/mayan-edms/mayan-edms/raw/master/docs/_static/overview.gif -.. |Installs badge| image:: http://img.shields.io/pypi/dm/mayan-edms.svg?style=flat - :target: https://crate.io/packages/mayan-edms/ .. |PyPI badge| image:: http://img.shields.io/pypi/v/mayan-edms.svg?style=flat :target: http://badge.fury.io/py/mayan-edms .. |License badge| image:: http://img.shields.io/badge/license-Apache%202.0-green.svg?style=flat From 07ac1cbbbe09551faf8225fc64412b022cb0a3d4 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Wed, 29 Jun 2016 19:02:34 -0400 Subject: [PATCH 09/10] Add version 2.1.3 release notes and update the changelog. --- HISTORY.rst | 4 +- docs/releases/2.1.3.rst | 87 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 docs/releases/2.1.3.rst diff --git a/HISTORY.rst b/HISTORY.rst index 2f3ac73d21..93d192eea4 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -1,10 +1,12 @@ -2.1.3 (2016-XX-XX) +2.1.3 (2016-06-29) - Add help message when initialsetup migration phase fails. Relates to GitLab issue #296. - Start using self.setdout instead of print as per documentation. - Fix GitLab issue #295, "When editing a user the top bar jumps to the name of the user". - Normalize handling of temporary file and directory creation. - Fix GitLab issue #309, "Temp files quickly filling-up my /tmp (1GB tmpfs)". - Explicitly check for residual temporary files in tests. +- Add missing temporary file cleanup for office documents. +- Fix file descriptor leak in the document signature download test. 2.1.2 (2016-05-20) ================== diff --git a/docs/releases/2.1.3.rst b/docs/releases/2.1.3.rst new file mode 100644 index 0000000000..f125db4843 --- /dev/null +++ b/docs/releases/2.1.3.rst @@ -0,0 +1,87 @@ +=============================== +Mayan EDMS v2.1.3 release notes +=============================== + +Released: June 29, 2016 + +What's new +========== + +This is a bug-fix release and all users are encouraged to upgrade. + +Temporary files cleanup +----------------------- +When uploading PDF files that had been OCRed by previous software, the text +parser backend that uses Poppler, would leave behind some temporary files in +the /tmp folder. The issue has been resolved and from the fix a test mixin +system check has been devised that will identify places in the codebase with +similar behaviors, reducing the recurrence of similar issues in the future. + +Other changes +------------- +- Add help message when initialsetup migration phase fails. Relates to GitLab issue #296 +- Start using self.setdout instead of print as per documentation. +- Fix GitLab issue #295, "When editing a user the top bar jumps to the name of the user". +- Normalize handling of temporary file and directory creation. +- Explicitly check for residual temporary files in tests. +- Add missing temporary file cleanup for office documents. +- Fix file descriptor leak in the document signature download test. + +Removals +-------- +* None + +Upgrading from a previous version +--------------------------------- + +Using PIP +~~~~~~~~~ + +Type in the console:: + + $ pip install -U mayan-edms + +the requirements will also be updated automatically. + +Using Git +~~~~~~~~~ + +If you installed Mayan EDMS by cloning the Git repository issue the commands:: + + $ git reset --hard HEAD + $ git pull + +otherwise download the compressed archived and uncompress it overriding the +existing installation. + +Next upgrade/add the new requirements:: + + $ pip install --upgrade -r requirements.txt + +Common steps +~~~~~~~~~~~~ + +Migrate existing database schema with:: + + $ mayan-edms.py performupgrade + +Add new static media:: + + $ mayan-edms.py collectstatic --noinput + +The upgrade procedure is now complete. + + +Backward incompatible changes +============================= + +* None + +Bugs fixed or issues closed +=========================== + +* `GitLab issue #295 `_ When editing a user the top bar jumps to the name of the user +* `GitLab issue #309 `_ Temp files quickly filling-up my /tmp (1GB tmpfs) + + +.. _PyPI: https://pypi.python.org/pypi/mayan-edms/ From 94833093329dc40e5ca567f694706c5e8c5150b9 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Wed, 29 Jun 2016 19:05:38 -0400 Subject: [PATCH 10/10] Bump version to 2.1.3. --- mayan/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mayan/__init__.py b/mayan/__init__.py index 011981549a..601f4c5e76 100644 --- a/mayan/__init__.py +++ b/mayan/__init__.py @@ -1,8 +1,8 @@ from __future__ import unicode_literals __title__ = 'Mayan EDMS' -__version__ = '2.1.2' -__build__ = 0x020102 +__version__ = '2.1.3' +__build__ = 0x020103 __author__ = 'Roberto Rosario' __author_email__ = 'roberto.rosario@mayan-edms.com' __description__ = 'Free Open Source Electronic Document Management System'