New argument --sync-offline-activity
This commit is contained in:
parent
1ae230639f
commit
722baba6e6
8 changed files with 127 additions and 3 deletions
|
@ -8,5 +8,6 @@ usage: wakatime [-h] [--entity FILE] [--key KEY] [--write] [--plugin PLUGIN]
|
||||||
[--exclude-unknown-project] [--include INCLUDE]
|
[--exclude-unknown-project] [--include INCLUDE]
|
||||||
[--include-only-with-project-file] [--extra-heartbeats]
|
[--include-only-with-project-file] [--extra-heartbeats]
|
||||||
[--log-file LOG_FILE] [--api-url API_URL] [--timeout TIMEOUT]
|
[--log-file LOG_FILE] [--api-url API_URL] [--timeout TIMEOUT]
|
||||||
|
[--sync-offline-activity SYNC_OFFLINE_ACTIVITY]
|
||||||
[--config CONFIG] [--verbose] [--version]
|
[--config CONFIG] [--verbose] [--version]
|
||||||
wakatime: error: Missing api key. Find your api key from wakatime.com/settings/api-key.
|
wakatime: error: Missing api key. Find your api key from wakatime.com/settings/api-key.
|
||||||
|
|
|
@ -8,5 +8,6 @@ usage: wakatime [-h] [--entity FILE] [--key KEY] [--write] [--plugin PLUGIN]
|
||||||
[--exclude-unknown-project] [--include INCLUDE]
|
[--exclude-unknown-project] [--include INCLUDE]
|
||||||
[--include-only-with-project-file] [--extra-heartbeats]
|
[--include-only-with-project-file] [--extra-heartbeats]
|
||||||
[--log-file LOG_FILE] [--api-url API_URL] [--timeout TIMEOUT]
|
[--log-file LOG_FILE] [--api-url API_URL] [--timeout TIMEOUT]
|
||||||
|
[--sync-offline-activity SYNC_OFFLINE_ACTIVITY]
|
||||||
[--config CONFIG] [--verbose] [--version]
|
[--config CONFIG] [--verbose] [--version]
|
||||||
wakatime: error: Missing api key. Find your api key from wakatime.com/settings/api-key.
|
wakatime: error: Missing api key. Find your api key from wakatime.com/settings/api-key.
|
||||||
|
|
|
@ -8,5 +8,6 @@ usage: wakatime [-h] [--entity FILE] [--key KEY] [--write] [--plugin PLUGIN]
|
||||||
[--exclude-unknown-project] [--include INCLUDE]
|
[--exclude-unknown-project] [--include INCLUDE]
|
||||||
[--include-only-with-project-file] [--extra-heartbeats]
|
[--include-only-with-project-file] [--extra-heartbeats]
|
||||||
[--log-file LOG_FILE] [--api-url API_URL] [--timeout TIMEOUT]
|
[--log-file LOG_FILE] [--api-url API_URL] [--timeout TIMEOUT]
|
||||||
|
[--sync-offline-activity SYNC_OFFLINE_ACTIVITY]
|
||||||
[--config CONFIG] [--verbose] [--version]
|
[--config CONFIG] [--verbose] [--version]
|
||||||
wakatime: error: argument --timeout: invalid int value: 'abc'
|
wakatime: error: argument --timeout: invalid int value: 'abc'
|
||||||
|
|
|
@ -8,6 +8,7 @@ usage: wakatime [-h] [--entity FILE] [--key KEY] [--write] [--plugin PLUGIN]
|
||||||
[--exclude-unknown-project] [--include INCLUDE]
|
[--exclude-unknown-project] [--include INCLUDE]
|
||||||
[--include-only-with-project-file] [--extra-heartbeats]
|
[--include-only-with-project-file] [--extra-heartbeats]
|
||||||
[--log-file LOG_FILE] [--api-url API_URL] [--timeout TIMEOUT]
|
[--log-file LOG_FILE] [--api-url API_URL] [--timeout TIMEOUT]
|
||||||
|
[--sync-offline-activity SYNC_OFFLINE_ACTIVITY]
|
||||||
[--config CONFIG] [--verbose] [--version]
|
[--config CONFIG] [--verbose] [--version]
|
||||||
|
|
||||||
Common interface for the WakaTime api.
|
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.
|
--api-url API_URL Heartbeats api url. For debugging with a local server.
|
||||||
--timeout TIMEOUT Number of seconds to wait when sending heartbeats to
|
--timeout TIMEOUT Number of seconds to wait when sending heartbeats to
|
||||||
api. Defaults to 60 seconds.
|
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.
|
--config CONFIG Defaults to ~/.wakatime.cfg.
|
||||||
--verbose Turns on debug messages in log file.
|
--verbose Turns on debug messages in log file.
|
||||||
--version show program's version number and exit
|
--version show program's version number and exit
|
||||||
|
|
|
@ -230,6 +230,96 @@ class ArgumentsTestCase(TestCase):
|
||||||
self.patched['wakatime.offlinequeue.Queue.push'].assert_not_called()
|
self.patched['wakatime.offlinequeue.Queue.push'].assert_not_called()
|
||||||
self.patched['wakatime.offlinequeue.Queue.pop'].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()
|
@log_capture()
|
||||||
def test_missing_api_key(self, logs):
|
def test_missing_api_key(self, logs):
|
||||||
logging.disable(logging.NOTSET)
|
logging.disable(logging.NOTSET)
|
||||||
|
|
|
@ -186,6 +186,17 @@ def parse_arguments():
|
||||||
action=StoreWithoutQuotes,
|
action=StoreWithoutQuotes,
|
||||||
help='Number of seconds to wait when sending ' +
|
help='Number of seconds to wait when sending ' +
|
||||||
'heartbeats to api. Defaults to 60 seconds.')
|
'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,
|
parser.add_argument('--config', dest='config', action=StoreWithoutQuotes,
|
||||||
help='Defaults to ~/.wakatime.cfg.')
|
help='Defaults to ~/.wakatime.cfg.')
|
||||||
parser.add_argument('--verbose', dest='verbose', action='store_true',
|
parser.add_argument('--verbose', dest='verbose', action='store_true',
|
||||||
|
@ -230,9 +241,20 @@ def parse_arguments():
|
||||||
if not args.entity:
|
if not args.entity:
|
||||||
if args.file:
|
if args.file:
|
||||||
args.entity = 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')
|
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:
|
if not args.language and args.alternate_language:
|
||||||
args.language = args.alternate_language
|
args.language = args.alternate_language
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,7 @@ def execute(argv=None):
|
||||||
retval = send_heartbeats(heartbeats, args, configs)
|
retval = send_heartbeats(heartbeats, args, configs)
|
||||||
if retval == SUCCESS:
|
if retval == SUCCESS:
|
||||||
queue = Queue(args, configs)
|
queue = Queue(args, configs)
|
||||||
offline_heartbeats = queue.pop_many()
|
offline_heartbeats = queue.pop_many(args.sync_offline_activity)
|
||||||
if len(offline_heartbeats) > 0:
|
if len(offline_heartbeats) > 0:
|
||||||
retval = send_heartbeats(offline_heartbeats, args, configs)
|
retval = send_heartbeats(offline_heartbeats, args, configs)
|
||||||
|
|
||||||
|
|
|
@ -109,7 +109,7 @@ class Queue(object):
|
||||||
heartbeats = []
|
heartbeats = []
|
||||||
|
|
||||||
count = 0
|
count = 0
|
||||||
while limit == 0 or count < limit:
|
while count < limit:
|
||||||
heartbeat = self.pop()
|
heartbeat = self.pop()
|
||||||
if not heartbeat:
|
if not heartbeat:
|
||||||
break
|
break
|
||||||
|
|
Loading…
Reference in a new issue