From 9b62bceb6b131a4e05aec87c9f06098b562d1fb8 Mon Sep 17 00:00:00 2001 From: Shriganesh Shintre Date: Tue, 30 May 2017 18:48:56 -0700 Subject: [PATCH] Enable autoversioning to output correct version This is an enhancement to enable rpm building with autogenerated version. This address https://github.com/box/ClusterRunner/issues/348. --- app/util/autoversioning.py | 44 ++++++++++++++++++--------- app/util/package_version.py | 1 - test/unit/util/test_autoversioning.py | 12 ++++---- 3 files changed, 36 insertions(+), 21 deletions(-) delete mode 100644 app/util/package_version.py diff --git a/app/util/autoversioning.py b/app/util/autoversioning.py index 31650ff..c21ed6c 100644 --- a/app/util/autoversioning.py +++ b/app/util/autoversioning.py @@ -20,18 +20,24 @@ def get_version(): :return: The version of the application :rtype: str """ - if getattr(sys, 'frozen', False): - return _get_frozen_package_version() # frozen/packaged - return _calculate_source_version() # unfrozen/running from source + return _get_frozen_package_version() or _calculate_source_version() or '0.0.0' def _try_rename(src, dst): try: os.rename(src, dst) - except FileExistsError: - # Skip backing up the original package_version.py if a FileExistsError happened. - # This might happen on Windows as NTFS doesn't support writing to a file while the file is opened in python. + except (FileExistsError, FileNotFoundError): + # Skip backing up the original package_version.py if a FileExistsError or FileNotFoundError happened. + # FileExistsError might happen on Windows as NTFS doesn't support writing to a file while the file + # is opened in python. + pass + + +def _try_remove(src): + try: + os.remove(src) + except OSError: pass @@ -70,8 +76,11 @@ def _get_frozen_package_version(): # only import package_version when needed as on Windows once imported, the actual package_version.py can't be # edited anymore - from app.util import package_version - return package_version.version + try: + from app.util import package_version + return package_version.version + except ImportError: + return None def _calculate_source_version(): @@ -79,15 +88,12 @@ def _calculate_source_version(): Calculate the version using a scheme based off of git repo info. Note that since this depends on the git history, this will *not* work from a frozen package (which does not include the git repo data). This will only work in the context of running the application from the cloned git repo. - - If one of the git commands used to calculate the version fails unexpectedly, the patch in the version string will - be set to "???". + If this is running outside of a git repo, it will handle the CalledProcessError exception and return None. :return: The version of the (source) application :rtype: str """ global _calculated_version - if _calculated_version is None: try: head_commit_hash = _get_commit_hash_from_revision_param('HEAD') @@ -97,9 +103,8 @@ def _calculate_source_version(): hash_extension = '' if head_commit_is_on_trunk else '-{}'.format(head_commit_hash[:7]) mod_extension = '' if not _repo_has_uncommited_changes() else '-mod' _calculated_version = '{}.{}{}{}'.format(_MAJOR_MINOR_VERSION, commit_count, hash_extension, mod_extension) - except subprocess.CalledProcessError: - _calculated_version = '{}.???'.format(_MAJOR_MINOR_VERSION) + _calculated_version = None return _calculated_version @@ -170,3 +175,14 @@ def _execute_local_git_command(*args): cwd=os.path.dirname(__file__), ) return command_output.decode() + + +if __name__ == '__main__': + """ + Print version string. + """ + # Remove the "package_version.py" file so that autoversioning always calculates version. + _try_remove(_VERSION_FILE_PATH) + version = get_version() + write_package_version_file(version) + print(version) diff --git a/app/util/package_version.py b/app/util/package_version.py deleted file mode 100644 index 06ae5e2..0000000 --- a/app/util/package_version.py +++ /dev/null @@ -1 +0,0 @@ -version = '0.0.0' # This should not be set to a real version. This file is modified during freeze. diff --git a/test/unit/util/test_autoversioning.py b/test/unit/util/test_autoversioning.py index 60ac4c7..bdca1ca 100644 --- a/test/unit/util/test_autoversioning.py +++ b/test/unit/util/test_autoversioning.py @@ -2,7 +2,7 @@ import subprocess from unittest.mock import MagicMock, call -from app.util import autoversioning, package_version +from app.util import autoversioning from test.framework.comparators import AnythingOfType from test.framework.base_unit_test_case import BaseUnitTestCase @@ -18,8 +18,8 @@ def setUp(self): autoversioning._calculated_version = None # reset cached version between individual tests def test_get_version_returns_frozen_version_when_run_from_frozen_package(self): - self.patch('app.util.autoversioning.sys').frozen = True - package_version.version = '1.2.3' # package_version is written during freeze, so this is the "frozen" version. + # package_version is written during freeze, so this is the "frozen" version. + self.patch('app.util.autoversioning._get_frozen_package_version').return_value = '1.2.3' actual_version = autoversioning.get_version() @@ -86,13 +86,13 @@ def test_calculate_source_version_caches_computed_version(self): self.assertEqual(num_check_output_calls, self.check_output_mock.call_count, 'No calls to check_output() should occur after the first get_version() call.') - def test_unexpected_failure_in_git_command_sets_patch_version_to_unknown(self): + def test_package_version_file_absent_and_unexpected_failure_in_git_command_sets_patch_version_to_default(self): self.check_output_mock.side_effect = [subprocess.CalledProcessError(1, 'fake')] # make all git commands fail actual_version = autoversioning.get_version() - self.assertEqual(actual_version, '1.0.???', 'get_version() should not raise exception if git commands fail, ' - 'and should just set the patch version to "???".') + self.assertEqual(actual_version, '0.0.0', 'get_version() should not raise exception if git commands fail, ' + 'and should just set the patch version to default "0.0.0".') @genty_dataset( head_commit_is_on_trunk=(True, False, '1.0.4'),