From 4ff8d88da3496a19ec505d8208bbe7363221eae9 Mon Sep 17 00:00:00 2001 From: Poruri Sai Rahul Date: Wed, 3 Jul 2019 13:56:40 +0530 Subject: [PATCH 1/7] FIX : Update cStringIO imports modified: apptools/logger/agent/attachments.py modified: apptools/logger/log_point.py modified: apptools/logger/plugin/logger_service.py --- apptools/logger/agent/attachments.py | 2 +- apptools/logger/log_point.py | 4 +++- apptools/logger/plugin/logger_service.py | 4 +++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/apptools/logger/agent/attachments.py b/apptools/logger/agent/attachments.py index fdf9839e2..4c6e60569 100644 --- a/apptools/logger/agent/attachments.py +++ b/apptools/logger/agent/attachments.py @@ -58,7 +58,7 @@ def _attach_directory(self, dir): relpath = os.path.basename(dir) import zipfile - from cStringIO import StringIO + from six.moves import cStringIO as StringIO ctype = 'application/octet-stream' maintype, subtype = ctype.split('/', 1) diff --git a/apptools/logger/log_point.py b/apptools/logger/log_point.py index 0e4321ff5..041662c88 100644 --- a/apptools/logger/log_point.py +++ b/apptools/logger/log_point.py @@ -19,7 +19,9 @@ # Standard library imports. import inspect -from cStringIO import StringIO + +# Third-party library imports. +from six.moves import cStringIO as StringIO def log_point(msg='\n'): diff --git a/apptools/logger/plugin/logger_service.py b/apptools/logger/plugin/logger_service.py index 26b01d7de..f553a9f0d 100644 --- a/apptools/logger/plugin/logger_service.py +++ b/apptools/logger/plugin/logger_service.py @@ -1,9 +1,11 @@ # Standard library imports -from cStringIO import StringIO import logging import os import zipfile +# Third-party library imports +from six.moves import cStringIO as StringIO + # Enthought library imports from pyface.workbench.api import View as WorkbenchView from traits.api import Any, Callable, HasTraits, Instance, List, \ From d5acc2ecbde440513df5e2e35cc07e64443b6646 Mon Sep 17 00:00:00 2001 From: poruri sai rahul Date: Tue, 8 Oct 2019 17:07:10 +0100 Subject: [PATCH 2/7] FIX : Use BytesIO where relevant instead of StringIO when used with zipfile.ZipFile, we need a BytesIO and not a StringIO object. also update the imports to be less verbose modified: apptools/logger/agent/attachments.py modified: apptools/logger/log_point.py modified: apptools/logger/plugin/logger_service.py --- apptools/logger/agent/attachments.py | 4 ++-- apptools/logger/log_point.py | 2 +- apptools/logger/plugin/logger_service.py | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apptools/logger/agent/attachments.py b/apptools/logger/agent/attachments.py index 4c6e60569..e51983283 100644 --- a/apptools/logger/agent/attachments.py +++ b/apptools/logger/agent/attachments.py @@ -58,13 +58,13 @@ def _attach_directory(self, dir): relpath = os.path.basename(dir) import zipfile - from six.moves import cStringIO as StringIO + from six import BytesIO ctype = 'application/octet-stream' maintype, subtype = ctype.split('/', 1) msg = MIMEBase(maintype, subtype) - file_object = StringIO() + file_object = BytesIO() zip = zipfile.ZipFile(file_object, 'w') _append_to_zip_archive(zip, dir, relpath) zip.close() diff --git a/apptools/logger/log_point.py b/apptools/logger/log_point.py index 041662c88..ce6205862 100644 --- a/apptools/logger/log_point.py +++ b/apptools/logger/log_point.py @@ -21,7 +21,7 @@ import inspect # Third-party library imports. -from six.moves import cStringIO as StringIO +from six import StringIO def log_point(msg='\n'): diff --git a/apptools/logger/plugin/logger_service.py b/apptools/logger/plugin/logger_service.py index f553a9f0d..3bad4fcfe 100644 --- a/apptools/logger/plugin/logger_service.py +++ b/apptools/logger/plugin/logger_service.py @@ -4,7 +4,7 @@ import zipfile # Third-party library imports -from six.moves import cStringIO as StringIO +from six import BytesIO # Enthought library imports from pyface.workbench.api import View as WorkbenchView @@ -110,7 +110,7 @@ def create_email_message(self, fromaddr, toaddrs, ccaddrs, subject, message.attach(msg) if include_userdata and len(self.mail_files) != 0: - f = StringIO() + f = BytesIO() zf = zipfile.ZipFile(f, 'w') for mf in self.mail_files: mf(zf) From f6291a410ce63a45b299a567f784f3009d789015 Mon Sep 17 00:00:00 2001 From: poruri sai rahul Date: Tue, 8 Oct 2019 18:02:42 +0100 Subject: [PATCH 3/7] TST : Add regression tests modified: apptools/logger/agent/attachments.py new file: apptools/logger/agent/tests/__init__.py new file: apptools/logger/agent/tests/test_attachments.py new file: apptools/logger/plugin/tests/__init__.py new file: apptools/logger/plugin/tests/test_logger_service.py --- apptools/logger/agent/attachments.py | 6 +- apptools/logger/agent/tests/__init__.py | 0 .../logger/agent/tests/test_attachments.py | 65 +++++++++++++++++++ apptools/logger/plugin/tests/__init__.py | 0 .../plugin/tests/test_logger_service.py | 43 ++++++++++++ 5 files changed, 111 insertions(+), 3 deletions(-) create mode 100644 apptools/logger/agent/tests/__init__.py create mode 100644 apptools/logger/agent/tests/test_attachments.py create mode 100644 apptools/logger/plugin/tests/__init__.py create mode 100644 apptools/logger/plugin/tests/test_logger_service.py diff --git a/apptools/logger/agent/attachments.py b/apptools/logger/agent/attachments.py index e51983283..0a56d0c3a 100644 --- a/apptools/logger/agent/attachments.py +++ b/apptools/logger/agent/attachments.py @@ -8,8 +8,8 @@ import logging import os.path -from email import Encoders -from email.MIMEBase import MIMEBase +from email import encoders +from email.mime.base import MIMEBase from traits.api import Any, HasTraits @@ -71,7 +71,7 @@ def _attach_directory(self, dir): msg.set_payload(file_object.getvalue()) - Encoders.encode_base64(msg) # Encode the payload using Base64 + encoders.encode_base64(msg) # Encode the payload using Base64 msg.add_header('Content-Disposition', 'attachment', filename='project.zip') self.message.attach(msg) diff --git a/apptools/logger/agent/tests/__init__.py b/apptools/logger/agent/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/apptools/logger/agent/tests/test_attachments.py b/apptools/logger/agent/tests/test_attachments.py new file mode 100644 index 000000000..76713674e --- /dev/null +++ b/apptools/logger/agent/tests/test_attachments.py @@ -0,0 +1,65 @@ +from email.mime.multipart import MIMEMultipart +import io +import os +import shutil +import tempfile +import unittest + +try: + # On Python 3, mock is part of the standard library, + from unittest import mock +except ImportError: + # Whereas on Python 2 it is not. + import mock + +from apptools.logger.agent.attachments import Attachments + + +class AttachmentsTestCase(unittest.TestCase): + def setUp(self): + self.tmpdir = tempfile.mkdtemp() + self.addCleanup(shutil.rmtree, self.tmpdir) + + self.tmpfile = os.path.join(self.tmpdir, "dummy_file.txt") + with io.open(self.tmpfile, 'w') as filehandle: + filehandle.write("Dummy data in dummy file for dummies") + + def test_attaching_workspace(self): + class DummyWorkspace(object): + path = self.tmpdir + + class MockedApplication(object): + tmpdir = self.tmpdir + def get_service(self, service_id): + return DummyWorkspace() + + attachments = Attachments( + application=MockedApplication(), + message=MIMEMultipart() + ) + attachments.package_workspace() + + message = attachments.message + self.assertTrue(message.is_multipart()) + payload = message.get_payload() + self.assertTrue(len(payload), 1) + + def test_attaching_single_project(self): + class DummySingleProject(object): + location = self.tmpdir + + class MockedApplication(object): + tmpdir = self.tmpdir + def get_service(self, service_id): + return DummySingleProject() + + attachments = Attachments( + application=MockedApplication(), + message=MIMEMultipart() + ) + attachments.package_single_project() + + message = attachments.message + self.assertTrue(message.is_multipart()) + payload = message.get_payload() + self.assertTrue(len(payload), 1) diff --git a/apptools/logger/plugin/tests/__init__.py b/apptools/logger/plugin/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/apptools/logger/plugin/tests/test_logger_service.py b/apptools/logger/plugin/tests/test_logger_service.py new file mode 100644 index 000000000..f5070fd5c --- /dev/null +++ b/apptools/logger/plugin/tests/test_logger_service.py @@ -0,0 +1,43 @@ +from email.mime.multipart import MIMEMultipart +import unittest + +try: + # On Python 3, mock is part of the standard library, + from unittest import mock +except ImportError: + # Whereas on Python 2 it is not. + import mock + +from apptools.logger.plugin.logger_service import LoggerService + + +class LoggerServiceTestCase(unittest.TestCase): + def test_create_email_message(self): + logger_service = LoggerService() + with mock.patch.object(logger_service, 'whole_log_text')\ + as mocked_log_txt: + mocked_log_txt.return_value = "Dummy log data" + msg = logger_service.create_email_message( + fromaddr='', toaddrs='', ccaddrs='', subject='', priority='' + ) + self.assertIsNotNone(msg) + self.assertIsInstance(msg, MIMEMultipart) + + def test_create_email_message_with_user_data(self): + # We used a mocked logger service which doesn't depend on the + # application trait and the presence of extensions to the extension + # point `apptools.logger.plugin.mail_files` + class MockedLoggerService(LoggerService): + def _get_mail_files(self): + return [lambda zip_file : None] + + logger_service = MockedLoggerService() + with mock.patch.object(logger_service, 'whole_log_text')\ + as mocked_log_txt: + mocked_log_txt.return_value = "Dummy log data" + msg = logger_service.create_email_message( + fromaddr='', toaddrs='', ccaddrs='', subject='', priority='', + include_userdata=True, + ) + self.assertIsNotNone(msg) + self.assertIsInstance(msg, MIMEMultipart) \ No newline at end of file From 0d75bd9e945dba01126e91c061b6a858de9967ed Mon Sep 17 00:00:00 2001 From: poruri sai rahul Date: Wed, 9 Oct 2019 14:26:06 +0100 Subject: [PATCH 4/7] Fix the test, pass unicode instead of str modified: apptools/logger/agent/tests/test_attachments.py --- apptools/logger/agent/tests/test_attachments.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apptools/logger/agent/tests/test_attachments.py b/apptools/logger/agent/tests/test_attachments.py index 76713674e..c8b9f5502 100644 --- a/apptools/logger/agent/tests/test_attachments.py +++ b/apptools/logger/agent/tests/test_attachments.py @@ -22,7 +22,7 @@ def setUp(self): self.tmpfile = os.path.join(self.tmpdir, "dummy_file.txt") with io.open(self.tmpfile, 'w') as filehandle: - filehandle.write("Dummy data in dummy file for dummies") + filehandle.write(u"Dummy data in dummy file for dummies") def test_attaching_workspace(self): class DummyWorkspace(object): From 0fb5cdc64308043c9b4c44b55946ee53316014a9 Mon Sep 17 00:00:00 2001 From: poruri sai rahul Date: Wed, 9 Oct 2019 14:35:37 +0100 Subject: [PATCH 5/7] REF : Use io.BytesIO everywhere instead of six.BytesIO modified: apptools/logger/agent/attachments.py modified: apptools/logger/agent/tests/test_attachments.py modified: apptools/logger/plugin/logger_service.py --- apptools/logger/agent/attachments.py | 2 +- apptools/logger/agent/tests/test_attachments.py | 2 +- apptools/logger/plugin/logger_service.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apptools/logger/agent/attachments.py b/apptools/logger/agent/attachments.py index 0a56d0c3a..3ef8a43c8 100644 --- a/apptools/logger/agent/attachments.py +++ b/apptools/logger/agent/attachments.py @@ -58,7 +58,7 @@ def _attach_directory(self, dir): relpath = os.path.basename(dir) import zipfile - from six import BytesIO + from io import BytesIO ctype = 'application/octet-stream' maintype, subtype = ctype.split('/', 1) diff --git a/apptools/logger/agent/tests/test_attachments.py b/apptools/logger/agent/tests/test_attachments.py index c8b9f5502..aa4f017b6 100644 --- a/apptools/logger/agent/tests/test_attachments.py +++ b/apptools/logger/agent/tests/test_attachments.py @@ -21,7 +21,7 @@ def setUp(self): self.addCleanup(shutil.rmtree, self.tmpdir) self.tmpfile = os.path.join(self.tmpdir, "dummy_file.txt") - with io.open(self.tmpfile, 'w') as filehandle: + with io.open(self.tmpfile, 'w', encoding='utf8') as filehandle: filehandle.write(u"Dummy data in dummy file for dummies") def test_attaching_workspace(self): diff --git a/apptools/logger/plugin/logger_service.py b/apptools/logger/plugin/logger_service.py index 3bad4fcfe..520cd0481 100644 --- a/apptools/logger/plugin/logger_service.py +++ b/apptools/logger/plugin/logger_service.py @@ -4,7 +4,7 @@ import zipfile # Third-party library imports -from six import BytesIO +from io import BytesIO # Enthought library imports from pyface.workbench.api import View as WorkbenchView From 4aef89ada9111f6f1c0a174cf547545837376f21 Mon Sep 17 00:00:00 2001 From: poruri sai rahul Date: Wed, 9 Oct 2019 14:39:12 +0100 Subject: [PATCH 6/7] FIX : assertEqual should be used modified: apptools/logger/agent/tests/test_attachments.py --- apptools/logger/agent/tests/test_attachments.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apptools/logger/agent/tests/test_attachments.py b/apptools/logger/agent/tests/test_attachments.py index aa4f017b6..499499817 100644 --- a/apptools/logger/agent/tests/test_attachments.py +++ b/apptools/logger/agent/tests/test_attachments.py @@ -42,7 +42,7 @@ def get_service(self, service_id): message = attachments.message self.assertTrue(message.is_multipart()) payload = message.get_payload() - self.assertTrue(len(payload), 1) + self.assertEqual(len(payload), 1) def test_attaching_single_project(self): class DummySingleProject(object): @@ -62,4 +62,4 @@ def get_service(self, service_id): message = attachments.message self.assertTrue(message.is_multipart()) payload = message.get_payload() - self.assertTrue(len(payload), 1) + self.assertEqual(len(payload), 1) From 327ef6aeb75b51b7f32fcee89d127750487e5ff3 Mon Sep 17 00:00:00 2001 From: poruri sai rahul Date: Wed, 9 Oct 2019 14:44:18 +0100 Subject: [PATCH 7/7] CLN : Remove unnecessary asserts modified: apptools/logger/plugin/tests/test_logger_service.py --- apptools/logger/plugin/tests/test_logger_service.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/apptools/logger/plugin/tests/test_logger_service.py b/apptools/logger/plugin/tests/test_logger_service.py index f5070fd5c..bfa298207 100644 --- a/apptools/logger/plugin/tests/test_logger_service.py +++ b/apptools/logger/plugin/tests/test_logger_service.py @@ -20,7 +20,6 @@ def test_create_email_message(self): msg = logger_service.create_email_message( fromaddr='', toaddrs='', ccaddrs='', subject='', priority='' ) - self.assertIsNotNone(msg) self.assertIsInstance(msg, MIMEMultipart) def test_create_email_message_with_user_data(self): @@ -39,5 +38,4 @@ def _get_mail_files(self): fromaddr='', toaddrs='', ccaddrs='', subject='', priority='', include_userdata=True, ) - self.assertIsNotNone(msg) - self.assertIsInstance(msg, MIMEMultipart) \ No newline at end of file + self.assertIsInstance(msg, MIMEMultipart)