add new AUTH_ERROR exit status to signal an invalid api key. fixes #41.
This commit is contained in:
parent
98de22c3a8
commit
33a87b9877
4 changed files with 118 additions and 48 deletions
|
@ -1,5 +1,5 @@
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
File "{file}", line 230, in parseArguments
|
File "{file}", line {lineno}, in parseArguments
|
||||||
args.timeout = int(configs.get('settings', 'timeout'))
|
args.timeout = int(configs.get('settings', 'timeout'))
|
||||||
ValueError: invalid literal for int() with base 10: 'abc'
|
ValueError: invalid literal for int() with base 10: 'abc'
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,15 @@ from wakatime.packages import requests
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
|
import re
|
||||||
import sys
|
import sys
|
||||||
from wakatime.compat import u
|
from wakatime.compat import u
|
||||||
|
from wakatime.constants import (
|
||||||
|
API_ERROR,
|
||||||
|
AUTH_ERROR,
|
||||||
|
CONFIG_FILE_PARSE_ERROR,
|
||||||
|
SUCCESS,
|
||||||
|
)
|
||||||
from wakatime.packages.requests.models import Response
|
from wakatime.packages.requests.models import Response
|
||||||
from . import utils
|
from . import utils
|
||||||
|
|
||||||
|
@ -54,7 +61,7 @@ class BaseTestCase(utils.TestCase):
|
||||||
args = ['--file', entity, '--key', '123', '--config', config]
|
args = ['--file', entity, '--key', '123', '--config', config]
|
||||||
|
|
||||||
retval = execute(args)
|
retval = execute(args)
|
||||||
self.assertEquals(retval, 0)
|
self.assertEquals(retval, SUCCESS)
|
||||||
self.assertEquals(sys.stdout.getvalue(), '')
|
self.assertEquals(sys.stdout.getvalue(), '')
|
||||||
self.assertEquals(sys.stderr.getvalue(), '')
|
self.assertEquals(sys.stderr.getvalue(), '')
|
||||||
|
|
||||||
|
@ -107,10 +114,11 @@ class BaseTestCase(utils.TestCase):
|
||||||
config = 'tests/samples/configs/has_everything.cfg'
|
config = 'tests/samples/configs/has_everything.cfg'
|
||||||
args = ['--file', entity, '--config', config]
|
args = ['--file', entity, '--config', config]
|
||||||
retval = execute(args)
|
retval = execute(args)
|
||||||
self.assertEquals(retval, 0)
|
self.assertEquals(retval, SUCCESS)
|
||||||
expected_stdout = open('tests/samples/output/main_test_good_config_file').read()
|
expected_stdout = open('tests/samples/output/main_test_good_config_file').read()
|
||||||
traceback_file = os.path.realpath('wakatime/main.py')
|
traceback_file = os.path.realpath('wakatime/main.py')
|
||||||
self.assertEquals(sys.stdout.getvalue(), expected_stdout.format(file=traceback_file))
|
lineno = int(re.search(r' line (\d+),', sys.stdout.getvalue()).group(1))
|
||||||
|
self.assertEquals(sys.stdout.getvalue(), expected_stdout.format(file=traceback_file, lineno=lineno))
|
||||||
self.assertEquals(sys.stderr.getvalue(), '')
|
self.assertEquals(sys.stderr.getvalue(), '')
|
||||||
|
|
||||||
self.patched['wakatime.session_cache.SessionCache.get'].assert_called_once_with()
|
self.patched['wakatime.session_cache.SessionCache.get'].assert_called_once_with()
|
||||||
|
@ -129,7 +137,7 @@ class BaseTestCase(utils.TestCase):
|
||||||
config = 'tests/samples/configs/sample_alternate_apikey.cfg'
|
config = 'tests/samples/configs/sample_alternate_apikey.cfg'
|
||||||
args = ['--file', entity, '--config', config]
|
args = ['--file', entity, '--config', config]
|
||||||
retval = execute(args)
|
retval = execute(args)
|
||||||
self.assertEquals(retval, 0)
|
self.assertEquals(retval, SUCCESS)
|
||||||
self.assertEquals(sys.stdout.getvalue(), '')
|
self.assertEquals(sys.stdout.getvalue(), '')
|
||||||
self.assertEquals(sys.stderr.getvalue(), '')
|
self.assertEquals(sys.stderr.getvalue(), '')
|
||||||
|
|
||||||
|
@ -145,7 +153,7 @@ class BaseTestCase(utils.TestCase):
|
||||||
config = 'tests/samples/configs/bad_config.cfg'
|
config = 'tests/samples/configs/bad_config.cfg'
|
||||||
args = ['--file', entity, '--config', config]
|
args = ['--file', entity, '--config', config]
|
||||||
retval = execute(args)
|
retval = execute(args)
|
||||||
self.assertEquals(retval, 103)
|
self.assertEquals(retval, CONFIG_FILE_PARSE_ERROR)
|
||||||
self.assertIn('ParsingError', sys.stdout.getvalue())
|
self.assertIn('ParsingError', sys.stdout.getvalue())
|
||||||
self.assertEquals(sys.stderr.getvalue(), '')
|
self.assertEquals(sys.stderr.getvalue(), '')
|
||||||
self.patched['wakatime.offlinequeue.Queue.push'].assert_not_called()
|
self.patched['wakatime.offlinequeue.Queue.push'].assert_not_called()
|
||||||
|
@ -165,7 +173,7 @@ class BaseTestCase(utils.TestCase):
|
||||||
args = ['--file', entity, '--key', '123', '--config', config, '--time', now]
|
args = ['--file', entity, '--key', '123', '--config', config, '--time', now]
|
||||||
|
|
||||||
retval = execute(args)
|
retval = execute(args)
|
||||||
self.assertEquals(retval, 102)
|
self.assertEquals(retval, API_ERROR)
|
||||||
self.assertEquals(sys.stdout.getvalue(), '')
|
self.assertEquals(sys.stdout.getvalue(), '')
|
||||||
self.assertEquals(sys.stderr.getvalue(), '')
|
self.assertEquals(sys.stderr.getvalue(), '')
|
||||||
|
|
||||||
|
@ -206,7 +214,7 @@ class BaseTestCase(utils.TestCase):
|
||||||
args = ['--file', entity, '--key', '123', '--config', config, '--time', now]
|
args = ['--file', entity, '--key', '123', '--config', config, '--time', now]
|
||||||
|
|
||||||
retval = execute(args)
|
retval = execute(args)
|
||||||
self.assertEquals(retval, 102)
|
self.assertEquals(retval, API_ERROR)
|
||||||
self.assertEquals(sys.stdout.getvalue(), '')
|
self.assertEquals(sys.stdout.getvalue(), '')
|
||||||
self.assertEquals(sys.stderr.getvalue(), '')
|
self.assertEquals(sys.stderr.getvalue(), '')
|
||||||
|
|
||||||
|
@ -266,7 +274,7 @@ class BaseTestCase(utils.TestCase):
|
||||||
|
|
||||||
|
|
||||||
retval = execute(args)
|
retval = execute(args)
|
||||||
self.assertEquals(retval, 102)
|
self.assertEquals(retval, API_ERROR)
|
||||||
self.assertEquals(sys.stdout.getvalue(), '')
|
self.assertEquals(sys.stdout.getvalue(), '')
|
||||||
self.assertEquals(sys.stderr.getvalue(), '')
|
self.assertEquals(sys.stderr.getvalue(), '')
|
||||||
|
|
||||||
|
@ -307,7 +315,7 @@ class BaseTestCase(utils.TestCase):
|
||||||
|
|
||||||
|
|
||||||
retval = execute(args)
|
retval = execute(args)
|
||||||
self.assertEquals(retval, 102)
|
self.assertEquals(retval, API_ERROR)
|
||||||
self.assertEquals(sys.stdout.getvalue(), '')
|
self.assertEquals(sys.stdout.getvalue(), '')
|
||||||
self.assertEquals(sys.stderr.getvalue(), '')
|
self.assertEquals(sys.stderr.getvalue(), '')
|
||||||
|
|
||||||
|
@ -318,6 +326,47 @@ class BaseTestCase(utils.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()
|
||||||
|
|
||||||
|
def test_401_response(self):
|
||||||
|
response = Response()
|
||||||
|
response.status_code = 401
|
||||||
|
self.patched['wakatime.packages.requests.adapters.HTTPAdapter.send'].return_value = response
|
||||||
|
|
||||||
|
now = u(int(time.time()))
|
||||||
|
|
||||||
|
args = ['--file', 'tests/samples/codefiles/twolinefile.txt', '--key', '123',
|
||||||
|
'--config', 'tests/samples/configs/paranoid.cfg', '--time', now]
|
||||||
|
|
||||||
|
|
||||||
|
retval = execute(args)
|
||||||
|
self.assertEquals(retval, AUTH_ERROR)
|
||||||
|
self.assertEquals(sys.stdout.getvalue(), '')
|
||||||
|
self.assertEquals(sys.stderr.getvalue(), '')
|
||||||
|
|
||||||
|
self.patched['wakatime.session_cache.SessionCache.delete'].assert_called_once_with()
|
||||||
|
self.patched['wakatime.session_cache.SessionCache.get'].assert_called_once_with()
|
||||||
|
self.patched['wakatime.session_cache.SessionCache.save'].assert_not_called()
|
||||||
|
|
||||||
|
heartbeat = {
|
||||||
|
'language': 'Text only',
|
||||||
|
'lines': 2,
|
||||||
|
'entity': 'HIDDEN.txt',
|
||||||
|
'project': os.path.basename(os.path.abspath('.')),
|
||||||
|
'branch': os.environ.get('TRAVIS_COMMIT', ANY),
|
||||||
|
'time': float(now),
|
||||||
|
'type': 'file',
|
||||||
|
}
|
||||||
|
stats = {
|
||||||
|
u('cursorpos'): None,
|
||||||
|
u('dependencies'): [],
|
||||||
|
u('language'): u('Text only'),
|
||||||
|
u('lineno'): None,
|
||||||
|
u('lines'): 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
self.patched['wakatime.offlinequeue.Queue.push'].assert_called_once_with(heartbeat, ANY, None)
|
||||||
|
self.assertEquals(stats, json.loads(self.patched['wakatime.offlinequeue.Queue.push'].call_args[0][1]))
|
||||||
|
self.patched['wakatime.offlinequeue.Queue.pop'].assert_not_called()
|
||||||
|
|
||||||
def test_alternate_project(self):
|
def test_alternate_project(self):
|
||||||
response = Response()
|
response = Response()
|
||||||
response.status_code = 0
|
response.status_code = 0
|
||||||
|
@ -330,7 +379,7 @@ class BaseTestCase(utils.TestCase):
|
||||||
args = ['--file', entity, '--alternate-project', 'xyz', '--config', config, '--time', now]
|
args = ['--file', entity, '--alternate-project', 'xyz', '--config', config, '--time', now]
|
||||||
|
|
||||||
retval = execute(args)
|
retval = execute(args)
|
||||||
self.assertEquals(retval, 102)
|
self.assertEquals(retval, API_ERROR)
|
||||||
self.assertEquals(sys.stdout.getvalue(), '')
|
self.assertEquals(sys.stdout.getvalue(), '')
|
||||||
self.assertEquals(sys.stderr.getvalue(), '')
|
self.assertEquals(sys.stderr.getvalue(), '')
|
||||||
|
|
||||||
|
@ -371,7 +420,7 @@ class BaseTestCase(utils.TestCase):
|
||||||
args = ['--file', entity, '--project', 'xyz', '--config', config, '--time', now]
|
args = ['--file', entity, '--project', 'xyz', '--config', config, '--time', now]
|
||||||
|
|
||||||
retval = execute(args)
|
retval = execute(args)
|
||||||
self.assertEquals(retval, 102)
|
self.assertEquals(retval, API_ERROR)
|
||||||
self.assertEquals(sys.stdout.getvalue(), '')
|
self.assertEquals(sys.stdout.getvalue(), '')
|
||||||
self.assertEquals(sys.stderr.getvalue(), '')
|
self.assertEquals(sys.stderr.getvalue(), '')
|
||||||
|
|
||||||
|
@ -409,7 +458,7 @@ class BaseTestCase(utils.TestCase):
|
||||||
config = 'tests/samples/configs/good_config.cfg'
|
config = 'tests/samples/configs/good_config.cfg'
|
||||||
args = ['--file', entity, '--config', config]
|
args = ['--file', entity, '--config', config]
|
||||||
retval = execute(args)
|
retval = execute(args)
|
||||||
self.assertEquals(retval, 0)
|
self.assertEquals(retval, SUCCESS)
|
||||||
self.assertEquals(sys.stdout.getvalue(), '')
|
self.assertEquals(sys.stdout.getvalue(), '')
|
||||||
self.assertEquals(sys.stderr.getvalue(), '')
|
self.assertEquals(sys.stderr.getvalue(), '')
|
||||||
|
|
||||||
|
@ -429,7 +478,7 @@ class BaseTestCase(utils.TestCase):
|
||||||
config = 'tests/samples/configs/good_config.cfg'
|
config = 'tests/samples/configs/good_config.cfg'
|
||||||
args = ['--file', entity, '--config', config, '--proxy', 'localhost:1234']
|
args = ['--file', entity, '--config', config, '--proxy', 'localhost:1234']
|
||||||
retval = execute(args)
|
retval = execute(args)
|
||||||
self.assertEquals(retval, 0)
|
self.assertEquals(retval, SUCCESS)
|
||||||
self.assertEquals(sys.stdout.getvalue(), '')
|
self.assertEquals(sys.stdout.getvalue(), '')
|
||||||
self.assertEquals(sys.stderr.getvalue(), '')
|
self.assertEquals(sys.stderr.getvalue(), '')
|
||||||
|
|
||||||
|
@ -454,7 +503,7 @@ class BaseTestCase(utils.TestCase):
|
||||||
args = ['--entity', entity, '--entitytype', 'domain', '--config', config, '--time', now]
|
args = ['--entity', entity, '--entitytype', 'domain', '--config', config, '--time', now]
|
||||||
retval = execute(args)
|
retval = execute(args)
|
||||||
|
|
||||||
self.assertEquals(retval, 102)
|
self.assertEquals(retval, API_ERROR)
|
||||||
self.assertEquals(sys.stdout.getvalue(), '')
|
self.assertEquals(sys.stdout.getvalue(), '')
|
||||||
self.assertEquals(sys.stderr.getvalue(), '')
|
self.assertEquals(sys.stderr.getvalue(), '')
|
||||||
|
|
||||||
|
@ -491,7 +540,7 @@ class BaseTestCase(utils.TestCase):
|
||||||
args = ['--entity', entity, '--entitytype', 'app', '--config', config, '--time', now]
|
args = ['--entity', entity, '--entitytype', 'app', '--config', config, '--time', now]
|
||||||
retval = execute(args)
|
retval = execute(args)
|
||||||
|
|
||||||
self.assertEquals(retval, 102)
|
self.assertEquals(retval, API_ERROR)
|
||||||
self.assertEquals(sys.stdout.getvalue(), '')
|
self.assertEquals(sys.stdout.getvalue(), '')
|
||||||
self.assertEquals(sys.stderr.getvalue(), '')
|
self.assertEquals(sys.stderr.getvalue(), '')
|
||||||
|
|
||||||
|
|
|
@ -13,3 +13,4 @@
|
||||||
SUCCESS = 0
|
SUCCESS = 0
|
||||||
API_ERROR = 102
|
API_ERROR = 102
|
||||||
CONFIG_FILE_PARSE_ERROR = 103
|
CONFIG_FILE_PARSE_ERROR = 103
|
||||||
|
AUTH_ERROR = 104
|
||||||
|
|
|
@ -30,7 +30,12 @@ sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), 'pac
|
||||||
|
|
||||||
from .__about__ import __version__
|
from .__about__ import __version__
|
||||||
from .compat import u, open, is_py3
|
from .compat import u, open, is_py3
|
||||||
from .constants import SUCCESS, API_ERROR, CONFIG_FILE_PARSE_ERROR
|
from .constants import (
|
||||||
|
API_ERROR,
|
||||||
|
AUTH_ERROR,
|
||||||
|
CONFIG_FILE_PARSE_ERROR,
|
||||||
|
SUCCESS,
|
||||||
|
)
|
||||||
from .logger import setup_logging
|
from .logger import setup_logging
|
||||||
from .offlinequeue import Queue
|
from .offlinequeue import Queue
|
||||||
from .packages import argparse
|
from .packages import argparse
|
||||||
|
@ -289,6 +294,9 @@ def send_heartbeat(project=None, branch=None, hostname=None, stats={}, key=None,
|
||||||
timestamp=None, isWrite=None, plugin=None, offline=None, entity_type='file',
|
timestamp=None, isWrite=None, plugin=None, offline=None, entity_type='file',
|
||||||
hidefilenames=None, proxy=None, api_url=None, timeout=None, **kwargs):
|
hidefilenames=None, proxy=None, api_url=None, timeout=None, **kwargs):
|
||||||
"""Sends heartbeat as POST request to WakaTime api server.
|
"""Sends heartbeat as POST request to WakaTime api server.
|
||||||
|
|
||||||
|
Returns `SUCCESS` when heartbeat was sent, otherwise returns an
|
||||||
|
error code constant.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not api_url:
|
if not api_url:
|
||||||
|
@ -375,7 +383,7 @@ def send_heartbeat(project=None, branch=None, hostname=None, stats={}, key=None,
|
||||||
'response_code': response_code,
|
'response_code': response_code,
|
||||||
})
|
})
|
||||||
session_cache.save(session)
|
session_cache.save(session)
|
||||||
return True
|
return SUCCESS
|
||||||
if offline:
|
if offline:
|
||||||
if response_code != 400:
|
if response_code != 400:
|
||||||
queue = Queue()
|
queue = Queue()
|
||||||
|
@ -385,6 +393,8 @@ def send_heartbeat(project=None, branch=None, hostname=None, stats={}, key=None,
|
||||||
'response_code': response_code,
|
'response_code': response_code,
|
||||||
'response_content': response_content,
|
'response_content': response_content,
|
||||||
})
|
})
|
||||||
|
session_cache.delete()
|
||||||
|
return AUTH_ERROR
|
||||||
elif log.isEnabledFor(logging.DEBUG):
|
elif log.isEnabledFor(logging.DEBUG):
|
||||||
log.warn({
|
log.warn({
|
||||||
'response_code': response_code,
|
'response_code': response_code,
|
||||||
|
@ -401,7 +411,39 @@ def send_heartbeat(project=None, branch=None, hostname=None, stats={}, key=None,
|
||||||
'response_content': response_content,
|
'response_content': response_content,
|
||||||
})
|
})
|
||||||
session_cache.delete()
|
session_cache.delete()
|
||||||
return False
|
return API_ERROR
|
||||||
|
|
||||||
|
|
||||||
|
def sync_offline_heartbeats(args, hostname):
|
||||||
|
"""Sends all heartbeats which were cached in the offline Queue."""
|
||||||
|
|
||||||
|
queue = Queue()
|
||||||
|
while True:
|
||||||
|
heartbeat = queue.pop()
|
||||||
|
if heartbeat is None:
|
||||||
|
break
|
||||||
|
status = send_heartbeat(
|
||||||
|
project=heartbeat['project'],
|
||||||
|
entity=heartbeat['entity'],
|
||||||
|
timestamp=heartbeat['time'],
|
||||||
|
branch=heartbeat['branch'],
|
||||||
|
hostname=hostname,
|
||||||
|
stats=json.loads(heartbeat['stats']),
|
||||||
|
key=args.key,
|
||||||
|
isWrite=heartbeat['is_write'],
|
||||||
|
plugin=heartbeat['plugin'],
|
||||||
|
offline=args.offline,
|
||||||
|
hidefilenames=args.hidefilenames,
|
||||||
|
entity_type=heartbeat['type'],
|
||||||
|
proxy=args.proxy,
|
||||||
|
api_url=args.api_url,
|
||||||
|
timeout=args.timeout,
|
||||||
|
)
|
||||||
|
if status != SUCCESS:
|
||||||
|
if status == AUTH_ERROR:
|
||||||
|
return AUTH_ERROR
|
||||||
|
break
|
||||||
|
return SUCCESS
|
||||||
|
|
||||||
|
|
||||||
def execute(argv=None):
|
def execute(argv=None):
|
||||||
|
@ -438,37 +480,15 @@ def execute(argv=None):
|
||||||
kwargs['project'] = project
|
kwargs['project'] = project
|
||||||
kwargs['branch'] = branch
|
kwargs['branch'] = branch
|
||||||
kwargs['stats'] = stats
|
kwargs['stats'] = stats
|
||||||
kwargs['hostname'] = args.hostname or socket.gethostname()
|
hostname = args.hostname or socket.gethostname()
|
||||||
|
kwargs['hostname'] = hostname
|
||||||
kwargs['timeout'] = args.timeout
|
kwargs['timeout'] = args.timeout
|
||||||
|
|
||||||
if send_heartbeat(**kwargs):
|
status = send_heartbeat(**kwargs)
|
||||||
queue = Queue()
|
if status == SUCCESS:
|
||||||
while True:
|
return sync_offline_heartbeats(args, hostname)
|
||||||
heartbeat = queue.pop()
|
else:
|
||||||
if heartbeat is None:
|
return status
|
||||||
break
|
|
||||||
sent = send_heartbeat(
|
|
||||||
project=heartbeat['project'],
|
|
||||||
entity=heartbeat['entity'],
|
|
||||||
timestamp=heartbeat['time'],
|
|
||||||
branch=heartbeat['branch'],
|
|
||||||
hostname=kwargs['hostname'],
|
|
||||||
stats=json.loads(heartbeat['stats']),
|
|
||||||
key=args.key,
|
|
||||||
isWrite=heartbeat['is_write'],
|
|
||||||
plugin=heartbeat['plugin'],
|
|
||||||
offline=args.offline,
|
|
||||||
hidefilenames=args.hidefilenames,
|
|
||||||
entity_type=heartbeat['type'],
|
|
||||||
proxy=args.proxy,
|
|
||||||
api_url=args.api_url,
|
|
||||||
timeout=args.timeout,
|
|
||||||
)
|
|
||||||
if not sent:
|
|
||||||
break
|
|
||||||
return SUCCESS
|
|
||||||
|
|
||||||
return API_ERROR
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
log.debug('File does not exist; ignoring this heartbeat.')
|
log.debug('File does not exist; ignoring this heartbeat.')
|
||||||
|
|
Loading…
Reference in a new issue