From 722baba6e64d85448ecf5a0a873e3530f89649b3 Mon Sep 17 00:00:00 2001 From: Alan Hamlett Date: Thu, 20 Sep 2018 09:08:09 -0700 Subject: [PATCH] New argument --sync-offline-activity --- ...onfig_file_not_passed_in_command_line_args | 1 + .../output/configs_test_missing_config_file | 1 + .../main_test_timeout_passed_via_command_line | 1 + tests/samples/output/test_help_contents | 9 ++ tests/test_arguments.py | 90 +++++++++++++++++++ wakatime/arguments.py | 24 ++++- wakatime/main.py | 2 +- wakatime/offlinequeue.py | 2 +- 8 files changed, 127 insertions(+), 3 deletions(-) diff --git a/tests/samples/output/configs_test_config_file_not_passed_in_command_line_args b/tests/samples/output/configs_test_config_file_not_passed_in_command_line_args index 6ac5453..1801fac 100644 --- a/tests/samples/output/configs_test_config_file_not_passed_in_command_line_args +++ b/tests/samples/output/configs_test_config_file_not_passed_in_command_line_args @@ -8,5 +8,6 @@ usage: wakatime [-h] [--entity FILE] [--key KEY] [--write] [--plugin PLUGIN] [--exclude-unknown-project] [--include INCLUDE] [--include-only-with-project-file] [--extra-heartbeats] [--log-file LOG_FILE] [--api-url API_URL] [--timeout TIMEOUT] + [--sync-offline-activity SYNC_OFFLINE_ACTIVITY] [--config CONFIG] [--verbose] [--version] wakatime: error: Missing api key. Find your api key from wakatime.com/settings/api-key. diff --git a/tests/samples/output/configs_test_missing_config_file b/tests/samples/output/configs_test_missing_config_file index 6ac5453..1801fac 100644 --- a/tests/samples/output/configs_test_missing_config_file +++ b/tests/samples/output/configs_test_missing_config_file @@ -8,5 +8,6 @@ usage: wakatime [-h] [--entity FILE] [--key KEY] [--write] [--plugin PLUGIN] [--exclude-unknown-project] [--include INCLUDE] [--include-only-with-project-file] [--extra-heartbeats] [--log-file LOG_FILE] [--api-url API_URL] [--timeout TIMEOUT] + [--sync-offline-activity SYNC_OFFLINE_ACTIVITY] [--config CONFIG] [--verbose] [--version] wakatime: error: Missing api key. Find your api key from wakatime.com/settings/api-key. diff --git a/tests/samples/output/main_test_timeout_passed_via_command_line b/tests/samples/output/main_test_timeout_passed_via_command_line index 463a116..f4ec1b9 100644 --- a/tests/samples/output/main_test_timeout_passed_via_command_line +++ b/tests/samples/output/main_test_timeout_passed_via_command_line @@ -8,5 +8,6 @@ usage: wakatime [-h] [--entity FILE] [--key KEY] [--write] [--plugin PLUGIN] [--exclude-unknown-project] [--include INCLUDE] [--include-only-with-project-file] [--extra-heartbeats] [--log-file LOG_FILE] [--api-url API_URL] [--timeout TIMEOUT] + [--sync-offline-activity SYNC_OFFLINE_ACTIVITY] [--config CONFIG] [--verbose] [--version] wakatime: error: argument --timeout: invalid int value: 'abc' diff --git a/tests/samples/output/test_help_contents b/tests/samples/output/test_help_contents index 841e410..84fbc68 100644 --- a/tests/samples/output/test_help_contents +++ b/tests/samples/output/test_help_contents @@ -8,6 +8,7 @@ usage: wakatime [-h] [--entity FILE] [--key KEY] [--write] [--plugin PLUGIN] [--exclude-unknown-project] [--include INCLUDE] [--include-only-with-project-file] [--extra-heartbeats] [--log-file LOG_FILE] [--api-url API_URL] [--timeout TIMEOUT] + [--sync-offline-activity SYNC_OFFLINE_ACTIVITY] [--config CONFIG] [--verbose] [--version] Common interface for the WakaTime api. @@ -76,6 +77,14 @@ optional arguments: --api-url API_URL Heartbeats api url. For debugging with a local server. --timeout TIMEOUT Number of seconds to wait when sending heartbeats to api. Defaults to 60 seconds. + --sync-offline-activity SYNC_OFFLINE_ACTIVITY + Amount of offline activity to sync from your local + ~/.wakatime.db sqlite3 file to your WakaTime Dashboard + before exiting. Can be "none" or a positive integer + number. Defaults to 5, meaning for every heartbeat + sent while online 5 offline heartbeats are synced. Can + be used without --entity to only sync offline activity + without generating new heartbeats. --config CONFIG Defaults to ~/.wakatime.cfg. --verbose Turns on debug messages in log file. --version show program's version number and exit diff --git a/tests/test_arguments.py b/tests/test_arguments.py index f76e196..3df6226 100644 --- a/tests/test_arguments.py +++ b/tests/test_arguments.py @@ -230,6 +230,96 @@ class ArgumentsTestCase(TestCase): self.patched['wakatime.offlinequeue.Queue.push'].assert_not_called() self.patched['wakatime.offlinequeue.Queue.pop'].assert_not_called() + @log_capture() + def test_missing_entity_argument_with_sync_offline_activity_arg(self, logs): + logging.disable(logging.NOTSET) + + self.patched['wakatime.packages.requests.adapters.HTTPAdapter.send'].return_value = CustomResponse() + + config = 'tests/samples/configs/good_config.cfg' + args = ['--config', config, '--sync-offline-activity', '5'] + + retval = execute(args) + + self.assertEquals(retval, SUCCESS) + self.assertNothingPrinted() + self.assertNothingLogged(logs) + + self.assertHeartbeatNotSavedOffline() + self.assertOfflineHeartbeatsSynced() + + @log_capture() + def test_missing_entity_argument_with_sync_offline_activity_none(self, logs): + logging.disable(logging.NOTSET) + + self.patched['wakatime.packages.requests.adapters.HTTPAdapter.send'].return_value = CustomResponse() + + config = 'tests/samples/configs/good_config.cfg' + args = ['--config', config, '--sync-offline-activity', 'none'] + + with self.assertRaises(SystemExit) as e: + execute(args) + + self.assertEquals(int(str(e.exception)), 2) + self.assertEquals(sys.stdout.getvalue(), '') + expected = 'error: argument --entity is required' + self.assertIn(expected, sys.stderr.getvalue()) + + log_output = u("\n").join([u(' ').join(x) for x in logs.actual()]) + expected = '' + self.assertEquals(log_output, expected) + + self.assertHeartbeatNotSavedOffline() + self.assertOfflineHeartbeatsNotSynced() + + @log_capture() + def test_invalid_sync_offline_activity(self, logs): + logging.disable(logging.NOTSET) + + self.patched['wakatime.packages.requests.adapters.HTTPAdapter.send'].return_value = CustomResponse() + + config = 'tests/samples/configs/good_config.cfg' + args = ['--config', config, '--sync-offline-activity', 'all'] + + with self.assertRaises(SystemExit) as e: + execute(args) + + self.assertEquals(int(str(e.exception)), 2) + self.assertEquals(sys.stdout.getvalue(), '') + expected = 'error: argument --sync-offline-activity must be "none" or an integer number' + self.assertIn(expected, sys.stderr.getvalue()) + + log_output = u("\n").join([u(' ').join(x) for x in logs.actual()]) + expected = '' + self.assertEquals(log_output, expected) + + self.assertHeartbeatNotSavedOffline() + self.assertOfflineHeartbeatsNotSynced() + + @log_capture() + def test_invalid_negative_sync_offline_activity(self, logs): + logging.disable(logging.NOTSET) + + self.patched['wakatime.packages.requests.adapters.HTTPAdapter.send'].return_value = CustomResponse() + + config = 'tests/samples/configs/good_config.cfg' + args = ['--config', config, '--sync-offline-activity', '-1'] + + with self.assertRaises(SystemExit) as e: + execute(args) + + self.assertEquals(int(str(e.exception)), 2) + self.assertEquals(sys.stdout.getvalue(), '') + expected = 'error: argument --sync-offline-activity must be "none" or an integer number' + self.assertIn(expected, sys.stderr.getvalue()) + + log_output = u("\n").join([u(' ').join(x) for x in logs.actual()]) + expected = '' + self.assertEquals(log_output, expected) + + self.assertHeartbeatNotSavedOffline() + self.assertOfflineHeartbeatsNotSynced() + @log_capture() def test_missing_api_key(self, logs): logging.disable(logging.NOTSET) diff --git a/wakatime/arguments.py b/wakatime/arguments.py index d57b62a..93ca291 100644 --- a/wakatime/arguments.py +++ b/wakatime/arguments.py @@ -186,6 +186,17 @@ def parse_arguments(): action=StoreWithoutQuotes, help='Number of seconds to wait when sending ' + 'heartbeats to api. Defaults to 60 seconds.') + parser.add_argument('--sync-offline-activity', + dest='sync_offline_activity', + action=StoreWithoutQuotes, + help='Amount of offline activity to sync from your ' + + 'local ~/.wakatime.db sqlite3 file to your ' + + 'WakaTime Dashboard before exiting. Can be ' + + '"none" or a positive integer number. Defaults ' + + 'to 5, meaning for every heartbeat sent while ' + + 'online 5 offline heartbeats are synced. Can ' + + 'be used without --entity to only sync offline ' + + 'activity without generating new heartbeats.') parser.add_argument('--config', dest='config', action=StoreWithoutQuotes, help='Defaults to ~/.wakatime.cfg.') parser.add_argument('--verbose', dest='verbose', action='store_true', @@ -230,9 +241,20 @@ def parse_arguments(): if not args.entity: if args.file: args.entity = args.file - else: + elif not args.sync_offline_activity or args.sync_offline_activity == 'none': parser.error('argument --entity is required') + if not args.sync_offline_activity: + args.sync_offline_activity = '5' + if args.sync_offline_activity == 'none': + args.sync_offline_activity = '0' + try: + args.sync_offline_activity = int(args.sync_offline_activity) + if args.sync_offline_activity < 0: + raise Exception('Error') + except: + parser.error('argument --sync-offline-activity must be "none" or an integer number') + if not args.language and args.alternate_language: args.language = args.alternate_language diff --git a/wakatime/main.py b/wakatime/main.py index 70dadfc..4dbaa25 100644 --- a/wakatime/main.py +++ b/wakatime/main.py @@ -66,7 +66,7 @@ def execute(argv=None): retval = send_heartbeats(heartbeats, args, configs) if retval == SUCCESS: queue = Queue(args, configs) - offline_heartbeats = queue.pop_many() + offline_heartbeats = queue.pop_many(args.sync_offline_activity) if len(offline_heartbeats) > 0: retval = send_heartbeats(offline_heartbeats, args, configs) diff --git a/wakatime/offlinequeue.py b/wakatime/offlinequeue.py index 8319b1b..fb43631 100644 --- a/wakatime/offlinequeue.py +++ b/wakatime/offlinequeue.py @@ -109,7 +109,7 @@ class Queue(object): heartbeats = [] count = 0 - while limit == 0 or count < limit: + while count < limit: heartbeat = self.pop() if not heartbeat: break