diff --git a/tests/test_arguments.py b/tests/test_arguments.py index 9a762e2..9fbd841 100644 --- a/tests/test_arguments.py +++ b/tests/test_arguments.py @@ -287,7 +287,7 @@ class MainTestCase(utils.TestCase): now = u(int(time.time())) key = str(uuid.uuid4()) - args = ['--file', entity, '--key', key, '--time', now] + args = ['--file', entity, '--key', key, '--time', now, '--config', 'fake-foobar'] retval = execute(args) self.assertEquals(sys.stdout.getvalue(), '') diff --git a/tests/test_main.py b/tests/test_main.py index 6920237..ac67843 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -15,6 +15,7 @@ from wakatime.compat import u, is_py3 from wakatime.constants import ( API_ERROR, AUTH_ERROR, + MAX_FILE_SIZE_SUPPORTED, SUCCESS, ) from wakatime.packages.requests.exceptions import RequestException @@ -561,3 +562,52 @@ class MainTestCase(utils.TestCase): self.patched['wakatime.offlinequeue.Queue.push'].assert_not_called() self.patched['wakatime.offlinequeue.Queue.pop'].assert_not_called() self.patched['wakatime.session_cache.SessionCache.get'].assert_not_called() + + def test_large_file_skips_lines_count(self): + response = Response() + response.status_code = 0 + self.patched['wakatime.packages.requests.adapters.HTTPAdapter.send'].return_value = response + + entity = 'tests/samples/codefiles/twolinefile.txt' + config = 'tests/samples/configs/good_config.cfg' + now = u(int(time.time())) + + args = ['--entity', entity, '--config', config, '--time', now] + + with utils.mock.patch('os.path.getsize') as mock_getsize: + mock_getsize.return_value = MAX_FILE_SIZE_SUPPORTED + 1 + + retval = execute(args) + self.assertEquals(retval, API_ERROR) + + self.assertEquals(sys.stdout.getvalue(), '') + self.assertEquals(sys.stderr.getvalue(), '') + + self.patched['wakatime.session_cache.SessionCache.get'].assert_called_once_with() + self.patched['wakatime.session_cache.SessionCache.delete'].assert_called_once_with() + self.patched['wakatime.session_cache.SessionCache.save'].assert_not_called() + + heartbeat = { + 'language': 'Text only', + 'lines': None, + 'entity': os.path.realpath(entity), + 'project': os.path.basename(os.path.abspath('.')), + 'cursorpos': None, + 'lineno': None, + 'branch': 'master', + 'time': float(now), + 'type': 'file', + } + stats = { + u('cursorpos'): None, + u('dependencies'): [], + u('language'): u('Text only'), + u('lineno'): None, + u('lines'): None, + } + + self.patched['wakatime.offlinequeue.Queue.push'].assert_called_once_with(ANY, ANY, None) + for key, val in self.patched['wakatime.offlinequeue.Queue.push'].call_args[0][0].items(): + self.assertEquals(heartbeat[key], val) + self.assertEquals(stats, json.loads(self.patched['wakatime.offlinequeue.Queue.push'].call_args[0][1])) + self.patched['wakatime.offlinequeue.Queue.pop'].assert_not_called() diff --git a/wakatime/configs.py b/wakatime/configs.py index 9ff9ec0..a4b2d18 100644 --- a/wakatime/configs.py +++ b/wakatime/configs.py @@ -25,6 +25,22 @@ except ImportError: from .packages import configparser +def getConfigFile(): + """Returns the config file location. + + If $WAKATIME_HOME env varialbe is defined, returns + $WAKATIME_HOME/.wakatime.cfg, otherwise ~/.wakatime.cfg. + """ + + fileName = '.wakatime.cfg' + + home = os.environ.get('WAKATIME_HOME') + if home: + return os.path.join(os.path.expanduser(home), fileName) + + return os.path.join(os.path.expanduser('~'), fileName) + + def parseConfigFile(configFile=None): """Returns a configparser.SafeConfigParser instance with configs read from the config file. Default location of the config file is @@ -32,13 +48,8 @@ def parseConfigFile(configFile=None): """ # get config file location from ENV - home = os.environ.get('WAKATIME_HOME') - if not configFile and home: - configFile = os.path.join(os.path.expanduser(home), '.wakatime.cfg') - - # use default config file location if not configFile: - configFile = os.path.join(os.path.expanduser('~'), '.wakatime.cfg') + configFile = getConfigFile() configs = configparser.ConfigParser(delimiters=('='), strict=False) try: diff --git a/wakatime/constants.py b/wakatime/constants.py index fece2b9..ae71737 100644 --- a/wakatime/constants.py +++ b/wakatime/constants.py @@ -38,3 +38,9 @@ UNKNOWN_ERROR = 105 Exit code used when the JSON input from `--extra-heartbeats` is malformed. """ MALFORMED_HEARTBEAT_ERROR = 106 + +""" Max file size supporting line number count stats. +Files larger than this in bytes will not have a line count stat for performance. +Default is 2MB. +""" +MAX_FILE_SIZE_SUPPORTED = 2000000 diff --git a/wakatime/stats.py b/wakatime/stats.py index f91ce01..e6fc3ff 100644 --- a/wakatime/stats.py +++ b/wakatime/stats.py @@ -15,6 +15,7 @@ import re import sys from .compat import u, open +from .constants import MAX_FILE_SIZE_SUPPORTED from .dependencies import DependencyParser from .language_priorities import LANGUAGES @@ -184,6 +185,11 @@ def get_language_from_extension(file_name): def number_lines_in_file(file_name): + try: + if os.path.getsize(file_name) > MAX_FILE_SIZE_SUPPORTED: + return None + except os.error: + pass lines = 0 try: with open(file_name, 'r', encoding='utf-8') as fh: