From adc50f7a08b285d31c139c5df662cee973bfd734 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Apitzsch?= Date: Sat, 31 Oct 2020 10:34:21 +0100 Subject: [PATCH 1/3] Bump required Python version to 3.5 --- README.md | 2 +- gramps/grampsapp.py | 2 +- setup.py | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6ecd7d7ed..f6cd600d7 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Requirements ============ The following packages **MUST** be installed in order for Gramps to work: -* **Python** 3.3 or greater - The programming language used by Gramps. https://www.python.org/ +* **Python** 3.5 or greater - The programming language used by Gramps. https://www.python.org/ * **GTK** 3.12 or greater - A cross-platform widget toolkit for creating graphical user interfaces. http://www.gtk.org/ * **pygobject** 3.12 or greater - Python Bindings for GLib/GObject/GIO/GTK+ https://wiki.gnome.org/Projects/PyGObject diff --git a/gramps/grampsapp.py b/gramps/grampsapp.py index f07ba2dda..2242aa27f 100644 --- a/gramps/grampsapp.py +++ b/gramps/grampsapp.py @@ -167,7 +167,7 @@ from .gen.mime import mime_type_is_defined # #------------------------------------------------------------------------- -MIN_PYTHON_VERSION = (3, 3, 0, '', 0) +MIN_PYTHON_VERSION = (3, 5, 0, '', 0) if not sys.version_info >= MIN_PYTHON_VERSION: logging.warning(_("Your Python version does not meet the " "requirements. At least python %(v1)d.%(v2)d.%(v3)d is needed to" diff --git a/setup.py b/setup.py index bfc000d29..7f243eced 100755 --- a/setup.py +++ b/setup.py @@ -29,8 +29,8 @@ Gramps distutils module. #check python version first import sys -if sys.version_info < (3, 2): - raise SystemExit("Gramps requires Python 3.2 or later.") +if sys.version_info < (3, 5): + raise SystemExit("Gramps requires Python 3.5 or later.") from distutils import log from setuptools import setup From 5d78b7aec3f00feb9c4cc508ab1bb9416a57132d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Apitzsch?= Date: Sat, 31 Oct 2020 10:36:50 +0100 Subject: [PATCH 2/3] Simplify code --- gramps/gen/db/generic.py | 14 ++------------ gramps/gui/display.py | 7 +------ 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/gramps/gen/db/generic.py b/gramps/gen/db/generic.py index f9b286f31..8cea16e90 100644 --- a/gramps/gen/db/generic.py +++ b/gramps/gen/db/generic.py @@ -35,6 +35,7 @@ import ast import sys import datetime import glob +from pathlib import Path #------------------------------------------------------------------------ # @@ -67,17 +68,6 @@ LOG = logging.getLogger(DBLOGNAME) SIGBASE = ('person', 'family', 'source', 'event', 'media', 'place', 'repository', 'reference', 'note', 'tag', 'citation') -def touch(fname, mode=0o666, dir_fd=None, **kwargs): - ## After http://stackoverflow.com/questions/1158076/implement-touch-using-python - if sys.version_info < (3, 3, 0): - with open(fname, 'a'): - os.utime(fname, None) # set to now - else: - flags = os.O_CREAT | os.O_APPEND - with os.fdopen(os.open(fname, flags=flags, mode=mode, dir_fd=dir_fd)) as f: - os.utime(f.fileno() if os.utime in os.supports_fd else fname, - dir_fd=None if os.supports_fd else dir_fd, **kwargs) - class DbGenericUndo(DbUndo): def __init__(self, grampsdb, path): super(DbGenericUndo, self).__init__(grampsdb) @@ -691,7 +681,7 @@ class DbGeneric(DbWriteBase, DbReadBase, UpdateCallback, Callback): # This is just a dummy file to indicate last modified time of # the database for gramps.cli.clidbman: filename = os.path.join(self._directory, "meta_data.db") - touch(filename) + Path(filename).touch() # Save metadata self._set_metadata('name_formats', self.name_formats) diff --git a/gramps/gui/display.py b/gramps/gui/display.py index 1388bc092..46f2288bd 100644 --- a/gramps/gui/display.py +++ b/gramps/gui/display.py @@ -75,9 +75,4 @@ def display_url(link, uistate=None): """ Open the specified URL in a browser. """ - if (mac() and sys.version_info.major == 3 and sys.version_info.minor < 5): - import subprocess - proc = subprocess.call(['/usr/bin/open', link], - stderr=subprocess.STDOUT) - else: - webbrowser.open_new_tab(link) + webbrowser.open_new_tab(link) From 4b964b12dc937bb9ea347329694f7a06c68416b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Apitzsch?= Date: Sat, 31 Oct 2020 10:45:57 +0100 Subject: [PATCH 3/3] Test: No need to check for mock support with Python 3.3+ --- gramps/cli/test/argparser_test.py | 14 +------ gramps/cli/test/user_test.py | 38 ++----------------- gramps/gen/utils/test/grampslocale_test.py | 30 ++++----------- gramps/gui/editors/test/editreference_test.py | 11 +----- gramps/gui/test/user_test.py | 15 +------- 5 files changed, 14 insertions(+), 94 deletions(-) diff --git a/gramps/cli/test/argparser_test.py b/gramps/cli/test/argparser_test.py index 734fc3b51..5a9e29cc0 100644 --- a/gramps/cli/test/argparser_test.py +++ b/gramps/cli/test/argparser_test.py @@ -22,20 +22,8 @@ """ Unittest for argparser.py """ import unittest +from unittest.mock import Mock from ..argparser import ArgParser -import sys - -try: - if sys.version_info < (3,3): - from mock import Mock - else: - from unittest.mock import Mock - - MOCKING = True - -except: - MOCKING = False - print ("Mocking disabled", sys.exc_info()[0:2]) class TestArgParser(unittest.TestCase): def setUp(self): diff --git a/gramps/cli/test/user_test.py b/gramps/cli/test/user_test.py index e8bc1f025..a72e82f67 100644 --- a/gramps/cli/test/user_test.py +++ b/gramps/cli/test/user_test.py @@ -22,21 +22,10 @@ """ Unittest for user.py """ import unittest +from unittest.mock import Mock, patch from .. import user import sys -try: - if sys.version_info < (3,3): - from mock import Mock, patch - else: - from unittest.mock import Mock, patch - - MOCKING = True - -except: - MOCKING = False - print ("Mocking disabled", sys.exc_info()[0:2]) - class TestUser: TITLE = "Testing prompt" MSG = "Choices are hard. Nevertheless, please choose!" @@ -46,10 +35,9 @@ class TestUser: class TestUser_prompt(unittest.TestCase): def setUp(self): self.real_user = user.User() - if MOCKING: - self.user = user.User() - self.user._fileout = Mock(spec=sys.stderr) - self.user._input = Mock(spec=input) + self.user = user.User() + self.user._fileout = Mock(spec=sys.stderr) + self.user._input = Mock(spec=input) def test_default_fileout_has_write(self): assert hasattr(self.real_user._fileout, 'write') @@ -57,7 +45,6 @@ class TestUser_prompt(unittest.TestCase): def test_default_input(self): assert self.real_user._input.__name__.endswith('input') - @unittest.skipUnless(MOCKING, "Requires unittest.mock to run") def test_prompt_returns_True_if_ACCEPT_entered(self): self.user._input.configure_mock(return_value = TestUser.ACCEPT) assert self.user.prompt( @@ -65,7 +52,6 @@ class TestUser_prompt(unittest.TestCase): ), "True expected!" self.user._input.assert_called_once_with() - @unittest.skipUnless(MOCKING, "Requires unittest.mock to run") def test_prompt_returns_False_if_REJECT_entered(self): self.user._input.configure_mock(return_value = TestUser.REJECT) assert not self.user.prompt( @@ -87,37 +73,24 @@ class TestUser_prompt(unittest.TestCase): "'{}' never printed in prompt: {}".format( text, self.user._fileout.method_calls)) - @unittest.skipUnless(MOCKING, "Requires unittest.mock to run") def test_prompt_contains_title_text(self): self.assert_prompt_contains_text(TestUser.TITLE) - @unittest.skipUnless(MOCKING, "Requires unittest.mock to run") def test_prompt_contains_msg_text(self): self.assert_prompt_contains_text(TestUser.MSG) - @unittest.skipUnless(MOCKING, "Requires unittest.mock to run") def test_prompt_contains_accept_text(self): self.assert_prompt_contains_text(TestUser.ACCEPT) - @unittest.skipUnless(MOCKING, "Requires unittest.mock to run") def test_prompt_contains_reject_text(self): self.assert_prompt_contains_text(TestUser.REJECT) - @unittest.skipUnless(MOCKING, "Requires unittest.mock to run") def test_prompt_strips_underscore_in_accept(self): self.assert_prompt_contains_text("accepT", accept="accep_T") - @unittest.skipUnless(MOCKING, "Requires unittest.mock to run") def test_prompt_strips_underscore_in_reject(self): self.assert_prompt_contains_text("reJect", reject="re_Ject") - if not MOCKING: #don't use SKIP, to avoid counting a skipped test - def test_manual_run(self): - b = self.real_user.prompt( - TestUser.TITLE, TestUser.MSG, TestUser.ACCEPT, TestUser.REJECT) - print ("Returned: {}".format(b)) - - @unittest.skipUnless(MOCKING, "Requires unittest.mock to run") def test_auto_accept_accepts_without_prompting(self): u = user.User(auto_accept=True) u._fileout = Mock(spec=sys.stderr) @@ -126,7 +99,6 @@ class TestUser_prompt(unittest.TestCase): ), "True expected!" assert len(u._fileout.method_calls) == 0, list(u._fileout.method_calls) - @unittest.skipUnless(MOCKING, "Requires unittest.mock to run") def test_EOFError_in_prompt_caught_as_False(self): self.user._input.configure_mock( side_effect = EOFError, @@ -136,7 +108,6 @@ class TestUser_prompt(unittest.TestCase): ), "False expected!" self.user._input.assert_called_once_with() -@unittest.skipUnless(MOCKING, "Requires unittest.mock to run") class TestUser_quiet(unittest.TestCase): def setUp(self): self.user = user.User(quiet=True) @@ -152,7 +123,6 @@ class TestUser_quiet(unittest.TestCase): assert len(self.user._fileout.method_calls ) == 0, list(self.user._fileout.method_calls) -@unittest.skipUnless(MOCKING, "Requires unittest.mock to run") class TestUser_progress(unittest.TestCase): def setUp(self): diff --git a/gramps/gen/utils/test/grampslocale_test.py b/gramps/gen/utils/test/grampslocale_test.py index 00e703ddc..e8146289b 100644 --- a/gramps/gen/utils/test/grampslocale_test.py +++ b/gramps/gen/utils/test/grampslocale_test.py @@ -20,19 +20,7 @@ # import unittest -import sys - -try: - if sys.version_info < (3,3): - from mock import Mock - else: - from unittest.mock import Mock - - MOCKING = True - -except: - MOCKING = False - print ("Mocking disabled, some testing skipped", sys.exc_info()[0:2]) +from unittest.mock import Mock class LexGettextTest(unittest.TestCase): SRC_WORD = "Inflect-me" @@ -45,19 +33,15 @@ class LexGettextTest(unittest.TestCase): self.trans = GrampsTranslations() def setup_sgettext_mock(self, msgval_expected): - if MOCKING: - mock = Mock(return_value=msgval_expected) - else: - mock = lambda msgid: msgval_expected + mock = Mock(return_value=msgval_expected) self.trans.sgettext = mock def tearDown(self): - if MOCKING: - try: - self.trans.sgettext.assert_called_once_with( - self.MSGID, self.CONTEXT) - except AttributeError as e: - print ("Apparently the test has never set up the mock: ", e) + try: + self.trans.sgettext.assert_called_once_with( + self.MSGID, self.CONTEXT) + except AttributeError as e: + print ("Apparently the test has never set up the mock: ", e) def testSrcWordOnlyIfNoTranslation(self): self.setup_sgettext_mock(self.SRC_WORD) diff --git a/gramps/gui/editors/test/editreference_test.py b/gramps/gui/editors/test/editreference_test.py index fe799857c..cb1f28767 100644 --- a/gramps/gui/editors/test/editreference_test.py +++ b/gramps/gui/editors/test/editreference_test.py @@ -21,16 +21,8 @@ """ Unittest for editreference.py """ import unittest -import sys +from unittest.mock import Mock, patch import os -try: - if sys.version_info < (3,3): - from mock import Mock, patch - else: - from unittest.mock import Mock, patch - MOCKING = True -except: - MOCKING = False from gramps.gen.lib import (Person, Family, Event, Source, Place, Citation, Repository, Media, Note, Tag) @@ -54,7 +46,6 @@ class MockEditReference(EditReference): class TestEditReference(unittest.TestCase): - @unittest.skipUnless(MOCKING, "Requires unittest.mock to run") def test_editreference(self): dbstate = DbState() db = make_database("sqlite") diff --git a/gramps/gui/test/user_test.py b/gramps/gui/test/user_test.py index 0e90b6c69..1afdbb192 100644 --- a/gramps/gui/test/user_test.py +++ b/gramps/gui/test/user_test.py @@ -22,20 +22,8 @@ """ Unittest for user.py """ import unittest +from unittest.mock import Mock, patch from .. import user -import sys - -try: - if sys.version_info < (3,3): - from mock import Mock, patch - else: - from unittest.mock import Mock, patch - - MOCKING = True - -except: - MOCKING = False - print ("Mocking disabled", sys.exc_info()[0:2]) class TestUser: TITLE = "Testing prompt" @@ -47,7 +35,6 @@ class TestUser_prompt(unittest.TestCase): def setUp(self): self.user = user.User() - @unittest.skipUnless(MOCKING, "Requires unittest.mock to run") def test_prompt_runs_QuestionDialog2(self): with patch('gramps.gui.user.QuestionDialog2') as MockQD: self.user.prompt(TestUser.TITLE, TestUser.MSG,