Ability to only track folders containing a .wakatime-project file
This commit is contained in:
parent
15408459af
commit
27e2d13788
22 changed files with 351 additions and 86 deletions
|
@ -60,7 +60,7 @@ format. An example config file with all available options::
|
||||||
[settings]
|
[settings]
|
||||||
debug = false
|
debug = false
|
||||||
api_key = your-api-key
|
api_key = your-api-key
|
||||||
hidefilenames = false
|
hide_filenames = false
|
||||||
exclude =
|
exclude =
|
||||||
^COMMIT_EDITMSG$
|
^COMMIT_EDITMSG$
|
||||||
^TAG_EDITMSG$
|
^TAG_EDITMSG$
|
||||||
|
@ -68,6 +68,7 @@ format. An example config file with all available options::
|
||||||
^/etc/
|
^/etc/
|
||||||
include =
|
include =
|
||||||
.*
|
.*
|
||||||
|
only_include_with_project_file = false
|
||||||
offline = true
|
offline = true
|
||||||
proxy = https://user:pass@localhost:8080
|
proxy = https://user:pass@localhost:8080
|
||||||
no_ssl_verify = false
|
no_ssl_verify = false
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
[settings]
|
[settings]
|
||||||
verbose = true
|
verbose = true
|
||||||
api_key = d491a956-c8f2-44a9-98a7-987814bd71ba
|
api_key = d491a956-c8f2-44a9-98a7-987814bd71ba
|
||||||
logfile = /tmp/waka
|
log_file = /tmp/waka
|
||||||
hidefilenames = true
|
hide_filenames = true
|
||||||
exclude =
|
exclude =
|
||||||
^COMMIT_EDITMSG$
|
^COMMIT_EDITMSG$
|
||||||
^TAG_EDITMSG$
|
^TAG_EDITMSG$
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[settings]
|
[settings]
|
||||||
debug = false
|
debug = false
|
||||||
api_key = 033c47c9-0441-4eb5-8b3f-b51f27b31049
|
api_key = 033c47c9-0441-4eb5-8b3f-b51f27b31049
|
||||||
hidefilenames =
|
hide_filenames =
|
||||||
missingfile
|
missingfile
|
||||||
python\.py$
|
python\.py$
|
||||||
|
|
3
tests/samples/configs/include_only_with_project_file.cfg
Normal file
3
tests/samples/configs/include_only_with_project_file.cfg
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[settings]
|
||||||
|
api_key = 1090a6ae-855f-4be7-b8fb-3edbaf1aa3ec
|
||||||
|
include_only_with_project_file = true
|
|
@ -1,4 +1,4 @@
|
||||||
[settings]
|
[settings]
|
||||||
debug = false
|
debug = false
|
||||||
api_key = 033c47c9-0441-4eb5-8b3f-b51f27b31049
|
api_key = 033c47c9-0441-4eb5-8b3f-b51f27b31049
|
||||||
hidefilenames = invalid(regex
|
hide_filenames = invalid(regex
|
||||||
|
|
|
@ -12,4 +12,4 @@ include =
|
||||||
\(invalid regex)
|
\(invalid regex)
|
||||||
includeme
|
includeme
|
||||||
offline = true
|
offline = true
|
||||||
hidefilenames = true
|
hide_filenames = true
|
||||||
|
|
15
tests/samples/configs/paranoid_legacy.cfg
Normal file
15
tests/samples/configs/paranoid_legacy.cfg
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
[settings]
|
||||||
|
debug = false
|
||||||
|
api_key = c21f8ebd-6a6a-48a0-900b-0870db3d7afe
|
||||||
|
api_url = https://api.wakatime.com/api/v1/heartbeats
|
||||||
|
ignore =
|
||||||
|
COMMIT_EDITMSG$
|
||||||
|
TAG_EDITMSG$
|
||||||
|
exclude =
|
||||||
|
excludeme
|
||||||
|
\(invalid regex)
|
||||||
|
include =
|
||||||
|
\(invalid regex)
|
||||||
|
includeme
|
||||||
|
offline = true
|
||||||
|
hidefilenames = true
|
|
@ -2,8 +2,9 @@ usage: wakatime [-h] [--entity FILE] [--key KEY] [--write] [--plugin PLUGIN]
|
||||||
[--time time] [--lineno LINENO] [--cursorpos CURSORPOS]
|
[--time time] [--lineno LINENO] [--cursorpos CURSORPOS]
|
||||||
[--entity-type ENTITY_TYPE] [--proxy PROXY] [--no-ssl-verify]
|
[--entity-type ENTITY_TYPE] [--proxy PROXY] [--no-ssl-verify]
|
||||||
[--project PROJECT] [--alternate-project ALTERNATE_PROJECT]
|
[--project PROJECT] [--alternate-project ALTERNATE_PROJECT]
|
||||||
[--language LANGUAGE] [--hostname HOSTNAME] [--disableoffline]
|
[--language LANGUAGE] [--hostname HOSTNAME]
|
||||||
[--hidefilenames] [--exclude EXCLUDE] [--include INCLUDE]
|
[--disable-offline] [--hide-filenames] [--exclude EXCLUDE]
|
||||||
[--extra-heartbeats] [--logfile LOGFILE] [--apiurl API_URL]
|
[--include INCLUDE] [--include-only-with-project-file]
|
||||||
|
[--extra-heartbeats] [--log-file LOG_FILE] [--api-url API_URL]
|
||||||
[--timeout TIMEOUT] [--config CONFIG] [--verbose] [--version]
|
[--timeout TIMEOUT] [--config CONFIG] [--verbose] [--version]
|
||||||
wakatime: error: Missing api key. Find your api key from wakatime.com/settings.
|
wakatime: error: Missing api key. Find your api key from wakatime.com/settings.
|
||||||
|
|
|
@ -2,8 +2,9 @@ usage: wakatime [-h] [--entity FILE] [--key KEY] [--write] [--plugin PLUGIN]
|
||||||
[--time time] [--lineno LINENO] [--cursorpos CURSORPOS]
|
[--time time] [--lineno LINENO] [--cursorpos CURSORPOS]
|
||||||
[--entity-type ENTITY_TYPE] [--proxy PROXY] [--no-ssl-verify]
|
[--entity-type ENTITY_TYPE] [--proxy PROXY] [--no-ssl-verify]
|
||||||
[--project PROJECT] [--alternate-project ALTERNATE_PROJECT]
|
[--project PROJECT] [--alternate-project ALTERNATE_PROJECT]
|
||||||
[--language LANGUAGE] [--hostname HOSTNAME] [--disableoffline]
|
[--language LANGUAGE] [--hostname HOSTNAME]
|
||||||
[--hidefilenames] [--exclude EXCLUDE] [--include INCLUDE]
|
[--disable-offline] [--hide-filenames] [--exclude EXCLUDE]
|
||||||
[--extra-heartbeats] [--logfile LOGFILE] [--apiurl API_URL]
|
[--include INCLUDE] [--include-only-with-project-file]
|
||||||
|
[--extra-heartbeats] [--log-file LOG_FILE] [--api-url API_URL]
|
||||||
[--timeout TIMEOUT] [--config CONFIG] [--verbose] [--version]
|
[--timeout TIMEOUT] [--config CONFIG] [--verbose] [--version]
|
||||||
wakatime: error: Missing api key. Find your api key from wakatime.com/settings.
|
wakatime: error: Missing api key. Find your api key from wakatime.com/settings.
|
||||||
|
|
|
@ -2,8 +2,9 @@ usage: wakatime [-h] [--entity FILE] [--key KEY] [--write] [--plugin PLUGIN]
|
||||||
[--time time] [--lineno LINENO] [--cursorpos CURSORPOS]
|
[--time time] [--lineno LINENO] [--cursorpos CURSORPOS]
|
||||||
[--entity-type ENTITY_TYPE] [--proxy PROXY] [--no-ssl-verify]
|
[--entity-type ENTITY_TYPE] [--proxy PROXY] [--no-ssl-verify]
|
||||||
[--project PROJECT] [--alternate-project ALTERNATE_PROJECT]
|
[--project PROJECT] [--alternate-project ALTERNATE_PROJECT]
|
||||||
[--language LANGUAGE] [--hostname HOSTNAME] [--disableoffline]
|
[--language LANGUAGE] [--hostname HOSTNAME]
|
||||||
[--hidefilenames] [--exclude EXCLUDE] [--include INCLUDE]
|
[--disable-offline] [--hide-filenames] [--exclude EXCLUDE]
|
||||||
[--extra-heartbeats] [--logfile LOGFILE] [--apiurl API_URL]
|
[--include INCLUDE] [--include-only-with-project-file]
|
||||||
|
[--extra-heartbeats] [--log-file LOG_FILE] [--api-url API_URL]
|
||||||
[--timeout TIMEOUT] [--config CONFIG] [--verbose] [--version]
|
[--timeout TIMEOUT] [--config CONFIG] [--verbose] [--version]
|
||||||
wakatime: error: argument --timeout: invalid int value: 'abc'
|
wakatime: error: argument --timeout: invalid int value: 'abc'
|
||||||
|
|
|
@ -2,9 +2,10 @@ usage: wakatime [-h] [--entity FILE] [--key KEY] [--write] [--plugin PLUGIN]
|
||||||
[--time time] [--lineno LINENO] [--cursorpos CURSORPOS]
|
[--time time] [--lineno LINENO] [--cursorpos CURSORPOS]
|
||||||
[--entity-type ENTITY_TYPE] [--proxy PROXY] [--no-ssl-verify]
|
[--entity-type ENTITY_TYPE] [--proxy PROXY] [--no-ssl-verify]
|
||||||
[--project PROJECT] [--alternate-project ALTERNATE_PROJECT]
|
[--project PROJECT] [--alternate-project ALTERNATE_PROJECT]
|
||||||
[--language LANGUAGE] [--hostname HOSTNAME] [--disableoffline]
|
[--language LANGUAGE] [--hostname HOSTNAME]
|
||||||
[--hidefilenames] [--exclude EXCLUDE] [--include INCLUDE]
|
[--disable-offline] [--hide-filenames] [--exclude EXCLUDE]
|
||||||
[--extra-heartbeats] [--logfile LOGFILE] [--apiurl API_URL]
|
[--include INCLUDE] [--include-only-with-project-file]
|
||||||
|
[--extra-heartbeats] [--log-file LOG_FILE] [--api-url API_URL]
|
||||||
[--timeout TIMEOUT] [--config CONFIG] [--verbose] [--version]
|
[--timeout TIMEOUT] [--config CONFIG] [--verbose] [--version]
|
||||||
|
|
||||||
Common interface for the WakaTime api.
|
Common interface for the WakaTime api.
|
||||||
|
@ -39,18 +40,21 @@ optional arguments:
|
||||||
--language LANGUAGE optional language name; if valid, takes priority over
|
--language LANGUAGE optional language name; if valid, takes priority over
|
||||||
auto-detected language
|
auto-detected language
|
||||||
--hostname HOSTNAME hostname of current machine.
|
--hostname HOSTNAME hostname of current machine.
|
||||||
--disableoffline disables offline time logging instead of queuing
|
--disable-offline disables offline time logging instead of queuing
|
||||||
logged time
|
logged time
|
||||||
--hidefilenames obfuscate file names; will not send file names to api
|
--hide-filenames obfuscate filenames; will not send file names to api
|
||||||
--exclude EXCLUDE filename patterns to exclude from logging; POSIX regex
|
--exclude EXCLUDE filename patterns to exclude from logging; POSIX regex
|
||||||
syntax; can be used more than once
|
syntax; can be used more than once
|
||||||
--include INCLUDE filename patterns to log; when used in combination
|
--include INCLUDE filename patterns to log; when used in combination
|
||||||
with --exclude, files matching include will still be
|
with --exclude, files matching include will still be
|
||||||
logged; POSIX regex syntax; can be used more than once
|
logged; POSIX regex syntax; can be used more than once
|
||||||
|
--include-only-with-project-file
|
||||||
|
disables tracking folders unless they contain a
|
||||||
|
.wakatime-project file; defaults to false
|
||||||
--extra-heartbeats reads extra heartbeats from STDIN as a JSON array
|
--extra-heartbeats reads extra heartbeats from STDIN as a JSON array
|
||||||
until EOF
|
until EOF
|
||||||
--logfile LOGFILE defaults to ~/.wakatime.log
|
--log-file LOG_FILE defaults to ~/.wakatime.log
|
||||||
--apiurl 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
|
||||||
--config CONFIG defaults to ~/.wakatime.cfg
|
--config CONFIG defaults to ~/.wakatime.cfg
|
||||||
|
|
|
@ -12,13 +12,16 @@ import sys
|
||||||
import uuid
|
import uuid
|
||||||
from testfixtures import log_capture
|
from testfixtures import log_capture
|
||||||
from wakatime.arguments import parse_arguments
|
from wakatime.arguments import parse_arguments
|
||||||
from wakatime.compat import u
|
from wakatime.compat import u, is_py3
|
||||||
from wakatime.constants import (
|
from wakatime.constants import (
|
||||||
|
API_ERROR,
|
||||||
AUTH_ERROR,
|
AUTH_ERROR,
|
||||||
SUCCESS,
|
SUCCESS,
|
||||||
)
|
)
|
||||||
|
from wakatime.packages.requests.exceptions import RequestException
|
||||||
|
from wakatime.packages.requests.models import Response
|
||||||
from wakatime.utils import get_user_agent
|
from wakatime.utils import get_user_agent
|
||||||
from .utils import mock, json, ANY, CustomResponse, TemporaryDirectory, TestCase
|
from .utils import mock, json, ANY, CustomResponse, TemporaryDirectory, TestCase, NamedTemporaryFile
|
||||||
|
|
||||||
|
|
||||||
class ArgumentsTestCase(TestCase):
|
class ArgumentsTestCase(TestCase):
|
||||||
|
@ -944,12 +947,103 @@ class ArgumentsTestCase(TestCase):
|
||||||
|
|
||||||
with mock.patch.object(sys, 'argv', ['wakatime'] + args):
|
with mock.patch.object(sys, 'argv', ['wakatime'] + args):
|
||||||
args, configs = parse_arguments()
|
args, configs = parse_arguments()
|
||||||
self.assertEquals(args.logfile, None)
|
self.assertEquals(args.log_file, None)
|
||||||
|
|
||||||
with mock.patch('os.environ.get') as mock_env:
|
with mock.patch('os.environ.get') as mock_env:
|
||||||
mock_env.return_value = os.path.realpath(tempdir)
|
mock_env.return_value = os.path.realpath(tempdir)
|
||||||
|
|
||||||
args, configs = parse_arguments()
|
args, configs = parse_arguments()
|
||||||
self.assertEquals(args.logfile, logfile)
|
self.assertEquals(args.log_file, logfile)
|
||||||
self.assertNothingPrinted()
|
self.assertNothingPrinted()
|
||||||
self.assertNothingLogged(logs)
|
self.assertNothingLogged(logs)
|
||||||
|
|
||||||
|
@log_capture()
|
||||||
|
def test_legacy_disableoffline_arg_supported(self, logs):
|
||||||
|
logging.disable(logging.NOTSET)
|
||||||
|
|
||||||
|
self.patched['wakatime.packages.requests.adapters.HTTPAdapter.send'].side_effect = RequestException('requests exception')
|
||||||
|
|
||||||
|
with TemporaryDirectory() as tempdir:
|
||||||
|
entity = 'tests/samples/codefiles/twolinefile.txt'
|
||||||
|
shutil.copy(entity, os.path.join(tempdir, 'twolinefile.txt'))
|
||||||
|
entity = os.path.realpath(os.path.join(tempdir, 'twolinefile.txt'))
|
||||||
|
now = u(int(time.time()))
|
||||||
|
key = str(uuid.uuid4())
|
||||||
|
|
||||||
|
args = ['--file', entity, '--key', key, '--disableoffline',
|
||||||
|
'--config', 'tests/samples/configs/good_config.cfg', '--time', now]
|
||||||
|
|
||||||
|
retval = execute(args)
|
||||||
|
self.assertEquals(retval, API_ERROR)
|
||||||
|
self.assertNothingPrinted()
|
||||||
|
|
||||||
|
log_output = u("\n").join([u(' ').join(x) for x in logs.actual()])
|
||||||
|
expected = "WakaTime ERROR {'RequestException': u'requests exception'}"
|
||||||
|
if is_py3:
|
||||||
|
expected = "WakaTime ERROR {'RequestException': 'requests exception'}"
|
||||||
|
self.assertEquals(expected, log_output)
|
||||||
|
|
||||||
|
self.assertHeartbeatSent()
|
||||||
|
self.assertHeartbeatNotSavedOffline()
|
||||||
|
self.assertOfflineHeartbeatsNotSynced()
|
||||||
|
self.assertSessionCacheDeleted()
|
||||||
|
|
||||||
|
def test_legacy_hidefilenames_arg_supported(self):
|
||||||
|
self.patched['wakatime.packages.requests.adapters.HTTPAdapter.send'].return_value = CustomResponse()
|
||||||
|
|
||||||
|
with TemporaryDirectory() as tempdir:
|
||||||
|
entity = 'tests/samples/codefiles/python.py'
|
||||||
|
shutil.copy(entity, os.path.join(tempdir, 'python.py'))
|
||||||
|
entity = os.path.realpath(os.path.join(tempdir, 'python.py'))
|
||||||
|
now = u(int(time.time()))
|
||||||
|
config = 'tests/samples/configs/good_config.cfg'
|
||||||
|
key = str(uuid.uuid4())
|
||||||
|
project = 'abcxyz'
|
||||||
|
|
||||||
|
args = ['--file', entity, '--key', key, '--config', config, '--time', now, '--hidefilenames', '--logfile', '~/.wakatime.log', '--alternate-project', project]
|
||||||
|
|
||||||
|
retval = execute(args)
|
||||||
|
self.assertEquals(retval, SUCCESS)
|
||||||
|
self.assertNothingPrinted()
|
||||||
|
|
||||||
|
heartbeat = {
|
||||||
|
'language': 'Python',
|
||||||
|
'lines': None,
|
||||||
|
'entity': 'HIDDEN.py',
|
||||||
|
'project': project,
|
||||||
|
'time': float(now),
|
||||||
|
'is_write': False,
|
||||||
|
'type': 'file',
|
||||||
|
'dependencies': None,
|
||||||
|
'user_agent': ANY,
|
||||||
|
}
|
||||||
|
self.assertHeartbeatSent(heartbeat)
|
||||||
|
|
||||||
|
self.assertHeartbeatNotSavedOffline()
|
||||||
|
self.assertOfflineHeartbeatsSynced()
|
||||||
|
self.assertSessionCacheSaved()
|
||||||
|
|
||||||
|
@log_capture()
|
||||||
|
def test_deprecated_logfile_arg_supported(self, logs):
|
||||||
|
logging.disable(logging.NOTSET)
|
||||||
|
|
||||||
|
response = Response()
|
||||||
|
response.status_code = 0
|
||||||
|
self.patched['wakatime.packages.requests.adapters.HTTPAdapter.send'].return_value = response
|
||||||
|
|
||||||
|
with NamedTemporaryFile() as fh:
|
||||||
|
now = u(int(time.time()))
|
||||||
|
entity = 'tests/samples/codefiles/python.py'
|
||||||
|
config = 'tests/samples/configs/good_config.cfg'
|
||||||
|
logfile = os.path.realpath(fh.name)
|
||||||
|
args = ['--file', entity, '--config', config, '--time', now, '--logfile', logfile]
|
||||||
|
|
||||||
|
execute(args)
|
||||||
|
|
||||||
|
retval = execute(args)
|
||||||
|
self.assertEquals(retval, 102)
|
||||||
|
self.assertNothingPrinted()
|
||||||
|
|
||||||
|
self.assertEquals(logging.WARNING, logging.getLogger('WakaTime').level)
|
||||||
|
self.assertEquals(logfile, logging.getLogger('WakaTime').handlers[0].baseFilename)
|
||||||
|
logs.check()
|
||||||
|
|
|
@ -42,7 +42,7 @@ class ConfigsTestCase(TestCase):
|
||||||
entity = 'tests/samples/codefiles/emptyfile.txt'
|
entity = 'tests/samples/codefiles/emptyfile.txt'
|
||||||
shutil.copy(entity, os.path.join(tempdir, 'emptyfile.txt'))
|
shutil.copy(entity, os.path.join(tempdir, 'emptyfile.txt'))
|
||||||
entity = os.path.realpath(os.path.join(tempdir, 'emptyfile.txt'))
|
entity = os.path.realpath(os.path.join(tempdir, 'emptyfile.txt'))
|
||||||
args = ['--file', entity, '--logfile', '~/.wakatime.log']
|
args = ['--file', entity, '--log-file', '~/.wakatime.log']
|
||||||
|
|
||||||
with mock.patch('wakatime.configs.os.environ.get') as mock_env:
|
with mock.patch('wakatime.configs.os.environ.get') as mock_env:
|
||||||
mock_env.return_value = None
|
mock_env.return_value = None
|
||||||
|
@ -77,7 +77,7 @@ class ConfigsTestCase(TestCase):
|
||||||
with mock.patch('wakatime.configs.os.environ.get') as mock_env:
|
with mock.patch('wakatime.configs.os.environ.get') as mock_env:
|
||||||
mock_env.return_value = tempdir
|
mock_env.return_value = tempdir
|
||||||
|
|
||||||
args = ['--file', entity, '--logfile', '~/.wakatime.log']
|
args = ['--file', entity, '--log-file', '~/.wakatime.log']
|
||||||
retval = execute(args)
|
retval = execute(args)
|
||||||
self.assertEquals(retval, SUCCESS)
|
self.assertEquals(retval, SUCCESS)
|
||||||
expected_stdout = open('tests/samples/output/configs_test_good_config_file').read()
|
expected_stdout = open('tests/samples/output/configs_test_good_config_file').read()
|
||||||
|
@ -100,7 +100,7 @@ class ConfigsTestCase(TestCase):
|
||||||
shutil.copy(entity, os.path.join(tempdir, 'emptyfile.txt'))
|
shutil.copy(entity, os.path.join(tempdir, 'emptyfile.txt'))
|
||||||
entity = os.path.realpath(os.path.join(tempdir, 'emptyfile.txt'))
|
entity = os.path.realpath(os.path.join(tempdir, 'emptyfile.txt'))
|
||||||
|
|
||||||
args = ['--file', entity, '--config', config, '--logfile', '~/.wakatime.log']
|
args = ['--file', entity, '--config', config, '--log-file', '~/.wakatime.log']
|
||||||
with self.assertRaises(SystemExit) as e:
|
with self.assertRaises(SystemExit) as e:
|
||||||
execute(args)
|
execute(args)
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ class ConfigsTestCase(TestCase):
|
||||||
entity = os.path.realpath(os.path.join(tempdir, 'emptyfile.txt'))
|
entity = os.path.realpath(os.path.join(tempdir, 'emptyfile.txt'))
|
||||||
|
|
||||||
config = 'tests/samples/configs/has_everything.cfg'
|
config = 'tests/samples/configs/has_everything.cfg'
|
||||||
args = ['--file', entity, '--config', config, '--logfile', '~/.wakatime.log']
|
args = ['--file', entity, '--config', config, '--log-file', '~/.wakatime.log']
|
||||||
retval = execute(args)
|
retval = execute(args)
|
||||||
self.assertEquals(retval, SUCCESS)
|
self.assertEquals(retval, SUCCESS)
|
||||||
expected_stdout = open('tests/samples/output/configs_test_good_config_file').read()
|
expected_stdout = open('tests/samples/output/configs_test_good_config_file').read()
|
||||||
|
@ -151,7 +151,7 @@ class ConfigsTestCase(TestCase):
|
||||||
entity = os.path.realpath(os.path.join(tempdir, 'emptyfile.txt'))
|
entity = os.path.realpath(os.path.join(tempdir, 'emptyfile.txt'))
|
||||||
|
|
||||||
config = 'tests/samples/configs/sample_alternate_apikey.cfg'
|
config = 'tests/samples/configs/sample_alternate_apikey.cfg'
|
||||||
args = ['--file', entity, '--config', config, '--logfile', '~/.wakatime.log']
|
args = ['--file', entity, '--config', config, '--log-file', '~/.wakatime.log']
|
||||||
retval = execute(args)
|
retval = execute(args)
|
||||||
self.assertEquals(retval, SUCCESS)
|
self.assertEquals(retval, SUCCESS)
|
||||||
self.assertEquals(sys.stdout.getvalue(), '')
|
self.assertEquals(sys.stdout.getvalue(), '')
|
||||||
|
@ -174,7 +174,7 @@ class ConfigsTestCase(TestCase):
|
||||||
entity = os.path.realpath(os.path.join(tempdir, 'emptyfile.txt'))
|
entity = os.path.realpath(os.path.join(tempdir, 'emptyfile.txt'))
|
||||||
|
|
||||||
config = 'tests/samples/configs/bad_config.cfg'
|
config = 'tests/samples/configs/bad_config.cfg'
|
||||||
args = ['--file', entity, '--config', config, '--logfile', '~/.wakatime.log']
|
args = ['--file', entity, '--config', config, '--log-file', '~/.wakatime.log']
|
||||||
|
|
||||||
with self.assertRaises(SystemExit) as e:
|
with self.assertRaises(SystemExit) as e:
|
||||||
execute(args)
|
execute(args)
|
||||||
|
@ -207,7 +207,7 @@ class ConfigsTestCase(TestCase):
|
||||||
config = 'tests/samples/configs/good_config.cfg'
|
config = 'tests/samples/configs/good_config.cfg'
|
||||||
key = str(uuid.uuid4())
|
key = str(uuid.uuid4())
|
||||||
|
|
||||||
args = ['--file', entity, '--key', key, '--config', config, '--time', now, '--logfile', '~/.wakatime.log']
|
args = ['--file', entity, '--key', key, '--config', config, '--time', now, '--log-file', '~/.wakatime.log']
|
||||||
|
|
||||||
retval = execute(args)
|
retval = execute(args)
|
||||||
self.assertEquals(retval, SUCCESS)
|
self.assertEquals(retval, SUCCESS)
|
||||||
|
@ -246,7 +246,42 @@ class ConfigsTestCase(TestCase):
|
||||||
key = u(uuid.uuid4())
|
key = u(uuid.uuid4())
|
||||||
project = 'abcxyz'
|
project = 'abcxyz'
|
||||||
|
|
||||||
args = ['--file', entity, '--key', key, '--config', config, '--time', now, '--logfile', '~/.wakatime.log', '--alternate-project', project]
|
args = ['--file', entity, '--key', key, '--config', config, '--time', now, '--log-file', '~/.wakatime.log', '--alternate-project', project]
|
||||||
|
|
||||||
|
retval = execute(args)
|
||||||
|
self.assertEquals(retval, SUCCESS)
|
||||||
|
self.assertNothingPrinted()
|
||||||
|
|
||||||
|
heartbeat = {
|
||||||
|
'language': 'Python',
|
||||||
|
'lines': None,
|
||||||
|
'entity': 'HIDDEN.py',
|
||||||
|
'project': project,
|
||||||
|
'time': float(now),
|
||||||
|
'is_write': False,
|
||||||
|
'type': 'file',
|
||||||
|
'dependencies': None,
|
||||||
|
'user_agent': ANY,
|
||||||
|
}
|
||||||
|
self.assertHeartbeatSent(heartbeat)
|
||||||
|
|
||||||
|
self.assertHeartbeatNotSavedOffline()
|
||||||
|
self.assertOfflineHeartbeatsSynced()
|
||||||
|
self.assertSessionCacheSaved()
|
||||||
|
|
||||||
|
def test_legacy_hidefilenames_config_supported(self):
|
||||||
|
self.patched['wakatime.packages.requests.adapters.HTTPAdapter.send'].return_value = CustomResponse()
|
||||||
|
|
||||||
|
with TemporaryDirectory() as tempdir:
|
||||||
|
entity = 'tests/samples/codefiles/python.py'
|
||||||
|
shutil.copy(entity, os.path.join(tempdir, 'python.py'))
|
||||||
|
entity = os.path.realpath(os.path.join(tempdir, 'python.py'))
|
||||||
|
now = u(int(time.time()))
|
||||||
|
config = 'tests/samples/configs/paranoid_legacy.cfg'
|
||||||
|
key = u(uuid.uuid4())
|
||||||
|
project = 'abcxyz'
|
||||||
|
|
||||||
|
args = ['--file', entity, '--key', key, '--config', config, '--time', now, '--log-file', '~/.wakatime.log', '--alternate-project', project]
|
||||||
|
|
||||||
retval = execute(args)
|
retval = execute(args)
|
||||||
self.assertEquals(retval, SUCCESS)
|
self.assertEquals(retval, SUCCESS)
|
||||||
|
@ -281,7 +316,7 @@ class ConfigsTestCase(TestCase):
|
||||||
key = str(uuid.uuid4())
|
key = str(uuid.uuid4())
|
||||||
project = 'abcxyz'
|
project = 'abcxyz'
|
||||||
|
|
||||||
args = ['--file', entity, '--key', key, '--config', config, '--time', now, '--hidefilenames', '--logfile', '~/.wakatime.log', '--alternate-project', project]
|
args = ['--file', entity, '--key', key, '--config', config, '--time', now, '--hide-filenames', '--log-file', '~/.wakatime.log', '--alternate-project', project]
|
||||||
|
|
||||||
retval = execute(args)
|
retval = execute(args)
|
||||||
self.assertEquals(retval, SUCCESS)
|
self.assertEquals(retval, SUCCESS)
|
||||||
|
@ -316,7 +351,7 @@ class ConfigsTestCase(TestCase):
|
||||||
key = '033c47c9-0441-4eb5-8b3f-b51f27b31049'
|
key = '033c47c9-0441-4eb5-8b3f-b51f27b31049'
|
||||||
project = 'abcxyz'
|
project = 'abcxyz'
|
||||||
|
|
||||||
args = ['--file', entity, '--key', key, '--config', config, '--time', now, '--logfile', '~/.wakatime.log', '--alternate-project', project]
|
args = ['--file', entity, '--key', key, '--config', config, '--time', now, '--log-file', '~/.wakatime.log', '--alternate-project', project]
|
||||||
|
|
||||||
retval = execute(args)
|
retval = execute(args)
|
||||||
self.assertEquals(retval, SUCCESS)
|
self.assertEquals(retval, SUCCESS)
|
||||||
|
@ -355,7 +390,7 @@ class ConfigsTestCase(TestCase):
|
||||||
dependencies = ['sqlalchemy', 'jinja', 'simplejson', 'flask', 'app', 'django', 'pygments', 'unittest', 'mock']
|
dependencies = ['sqlalchemy', 'jinja', 'simplejson', 'flask', 'app', 'django', 'pygments', 'unittest', 'mock']
|
||||||
project = 'abcxyz'
|
project = 'abcxyz'
|
||||||
|
|
||||||
args = ['--file', entity, '--key', key, '--config', config, '--time', now, '--logfile', '~/.wakatime.log', '--alternate-project', project]
|
args = ['--file', entity, '--key', key, '--config', config, '--time', now, '--log-file', '~/.wakatime.log', '--alternate-project', project]
|
||||||
|
|
||||||
retval = execute(args)
|
retval = execute(args)
|
||||||
self.assertEquals(retval, SUCCESS)
|
self.assertEquals(retval, SUCCESS)
|
||||||
|
@ -392,7 +427,7 @@ class ConfigsTestCase(TestCase):
|
||||||
config = 'tests/samples/configs/invalid_hide_file_names.cfg'
|
config = 'tests/samples/configs/invalid_hide_file_names.cfg'
|
||||||
key = str(uuid.uuid4())
|
key = str(uuid.uuid4())
|
||||||
|
|
||||||
args = ['--file', entity, '--key', key, '--config', config, '--time', now, '--logfile', '~/.wakatime.log']
|
args = ['--file', entity, '--key', key, '--config', config, '--time', now, '--log-file', '~/.wakatime.log']
|
||||||
|
|
||||||
retval = execute(args)
|
retval = execute(args)
|
||||||
self.assertEquals(retval, SUCCESS)
|
self.assertEquals(retval, SUCCESS)
|
||||||
|
@ -438,7 +473,7 @@ class ConfigsTestCase(TestCase):
|
||||||
entity = os.path.realpath(os.path.join(tempdir, 'emptyfile.txt'))
|
entity = os.path.realpath(os.path.join(tempdir, 'emptyfile.txt'))
|
||||||
config = 'tests/samples/configs/good_config.cfg'
|
config = 'tests/samples/configs/good_config.cfg'
|
||||||
|
|
||||||
args = ['--file', entity, '--config', config, '--exclude', 'empty', '--verbose', '--logfile', '~/.wakatime.log']
|
args = ['--file', entity, '--config', config, '--exclude', 'empty', '--verbose', '--log-file', '~/.wakatime.log']
|
||||||
retval = execute(args)
|
retval = execute(args)
|
||||||
self.assertEquals(retval, SUCCESS)
|
self.assertEquals(retval, SUCCESS)
|
||||||
self.assertNothingPrinted()
|
self.assertNothingPrinted()
|
||||||
|
@ -452,6 +487,77 @@ class ConfigsTestCase(TestCase):
|
||||||
self.assertOfflineHeartbeatsSynced()
|
self.assertOfflineHeartbeatsSynced()
|
||||||
self.assertSessionCacheUntouched()
|
self.assertSessionCacheUntouched()
|
||||||
|
|
||||||
|
@log_capture()
|
||||||
|
def test_exclude_file_without_project_file(self, logs):
|
||||||
|
logging.disable(logging.NOTSET)
|
||||||
|
|
||||||
|
response = Response()
|
||||||
|
response.status_code = 0
|
||||||
|
self.patched['wakatime.packages.requests.adapters.HTTPAdapter.send'].return_value = response
|
||||||
|
|
||||||
|
with TemporaryDirectory() as tempdir:
|
||||||
|
entity = 'tests/samples/codefiles/emptyfile.txt'
|
||||||
|
shutil.copy(entity, os.path.join(tempdir, 'emptyfile.txt'))
|
||||||
|
entity = os.path.realpath(os.path.join(tempdir, 'emptyfile.txt'))
|
||||||
|
config = 'tests/samples/configs/include_only_with_project_file.cfg'
|
||||||
|
|
||||||
|
args = ['--file', entity, '--config', config, '--verbose', '--log-file', '~/.wakatime.log']
|
||||||
|
retval = execute(args)
|
||||||
|
self.assertEquals(retval, SUCCESS)
|
||||||
|
self.assertNothingPrinted()
|
||||||
|
actual = self.getLogOutput(logs)
|
||||||
|
expected = 'WakaTime DEBUG Skipping because missing .wakatime-project file in parent path.'
|
||||||
|
self.assertEquals(actual, expected)
|
||||||
|
|
||||||
|
self.assertHeartbeatNotSent()
|
||||||
|
|
||||||
|
self.assertHeartbeatNotSavedOffline()
|
||||||
|
self.assertOfflineHeartbeatsSynced()
|
||||||
|
self.assertSessionCacheUntouched()
|
||||||
|
|
||||||
|
@log_capture()
|
||||||
|
def test_include_file_with_project_file(self, logs):
|
||||||
|
logging.disable(logging.NOTSET)
|
||||||
|
|
||||||
|
self.patched['wakatime.packages.requests.adapters.HTTPAdapter.send'].return_value = CustomResponse()
|
||||||
|
|
||||||
|
with TemporaryDirectory() as tempdir:
|
||||||
|
entity = 'tests/samples/codefiles/emptyfile.txt'
|
||||||
|
shutil.copy(entity, os.path.join(tempdir, 'emptyfile.txt'))
|
||||||
|
entity = os.path.realpath(os.path.join(tempdir, 'emptyfile.txt'))
|
||||||
|
config = 'tests/samples/configs/include_only_with_project_file.cfg'
|
||||||
|
project = 'abcxyz'
|
||||||
|
now = u(int(time.time()))
|
||||||
|
|
||||||
|
with open(os.path.join(tempdir, '.wakatime-project'), 'w'):
|
||||||
|
pass
|
||||||
|
|
||||||
|
args = ['--file', entity, '--config', config, '--time', now, '--verbose', '--log-file', '~/.wakatime.log', '--project', project]
|
||||||
|
retval = execute(args)
|
||||||
|
|
||||||
|
self.assertEquals(retval, SUCCESS)
|
||||||
|
self.assertNothingPrinted()
|
||||||
|
|
||||||
|
heartbeat = {
|
||||||
|
'language': 'Text only',
|
||||||
|
'lines': 0,
|
||||||
|
'entity': os.path.realpath(entity),
|
||||||
|
'project': project,
|
||||||
|
'branch': ANY,
|
||||||
|
'cursorpos': None,
|
||||||
|
'lineno': None,
|
||||||
|
'time': float(now),
|
||||||
|
'is_write': False,
|
||||||
|
'type': 'file',
|
||||||
|
'dependencies': [],
|
||||||
|
'user_agent': ANY,
|
||||||
|
}
|
||||||
|
self.assertHeartbeatSent(heartbeat)
|
||||||
|
|
||||||
|
self.assertHeartbeatNotSavedOffline()
|
||||||
|
self.assertOfflineHeartbeatsSynced()
|
||||||
|
self.assertSessionCacheSaved()
|
||||||
|
|
||||||
def test_hostname_set_from_config_file(self):
|
def test_hostname_set_from_config_file(self):
|
||||||
self.patched['wakatime.packages.requests.adapters.HTTPAdapter.send'].return_value = CustomResponse()
|
self.patched['wakatime.packages.requests.adapters.HTTPAdapter.send'].return_value = CustomResponse()
|
||||||
|
|
||||||
|
@ -462,7 +568,7 @@ class ConfigsTestCase(TestCase):
|
||||||
|
|
||||||
hostname = 'fromcfgfile'
|
hostname = 'fromcfgfile'
|
||||||
config = 'tests/samples/configs/has_everything.cfg'
|
config = 'tests/samples/configs/has_everything.cfg'
|
||||||
args = ['--file', entity, '--config', config, '--timeout', '15', '--logfile', '~/.wakatime.log']
|
args = ['--file', entity, '--config', config, '--timeout', '15', '--log-file', '~/.wakatime.log']
|
||||||
retval = execute(args)
|
retval = execute(args)
|
||||||
self.assertEquals(retval, SUCCESS)
|
self.assertEquals(retval, SUCCESS)
|
||||||
self.assertNothingPrinted()
|
self.assertNothingPrinted()
|
||||||
|
@ -485,7 +591,7 @@ class ConfigsTestCase(TestCase):
|
||||||
entity = os.path.realpath(os.path.join(tempdir, 'emptyfile.txt'))
|
entity = os.path.realpath(os.path.join(tempdir, 'emptyfile.txt'))
|
||||||
|
|
||||||
config = 'tests/samples/configs/has_ssl_verify_disabled.cfg'
|
config = 'tests/samples/configs/has_ssl_verify_disabled.cfg'
|
||||||
args = ['--file', entity, '--config', config, '--timeout', '15', '--logfile', '~/.wakatime.log']
|
args = ['--file', entity, '--config', config, '--timeout', '15', '--log-file', '~/.wakatime.log']
|
||||||
retval = execute(args)
|
retval = execute(args)
|
||||||
self.assertEquals(retval, SUCCESS)
|
self.assertEquals(retval, SUCCESS)
|
||||||
self.assertNothingPrinted()
|
self.assertNothingPrinted()
|
||||||
|
|
|
@ -17,9 +17,10 @@ class HeartbeatTestCase(TestCase):
|
||||||
|
|
||||||
class Args(object):
|
class Args(object):
|
||||||
exclude = []
|
exclude = []
|
||||||
hidefilenames = ['.*']
|
hide_filenames = ['.*']
|
||||||
include = []
|
include = []
|
||||||
plugin = None
|
plugin = None
|
||||||
|
include_only_with_project_file = None
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
'entity': os.path.realpath('tests/samples/codefiles/python.py'),
|
'entity': os.path.realpath('tests/samples/codefiles/python.py'),
|
||||||
|
@ -49,9 +50,10 @@ class HeartbeatTestCase(TestCase):
|
||||||
|
|
||||||
class Args(object):
|
class Args(object):
|
||||||
exclude = []
|
exclude = []
|
||||||
hidefilenames = []
|
hide_filenames = []
|
||||||
include = []
|
include = []
|
||||||
plugin = None
|
plugin = None
|
||||||
|
include_only_with_project_file = None
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
'entity': os.path.realpath('tests/samples/codefiles/python.py'),
|
'entity': os.path.realpath('tests/samples/codefiles/python.py'),
|
||||||
|
@ -72,7 +74,7 @@ class HeartbeatTestCase(TestCase):
|
||||||
logging.disable(logging.NOTSET)
|
logging.disable(logging.NOTSET)
|
||||||
|
|
||||||
class Args(object):
|
class Args(object):
|
||||||
hidefilenames = ['.*']
|
hide_filenames = ['.*']
|
||||||
plugin = None
|
plugin = None
|
||||||
|
|
||||||
branch = 'abc123'
|
branch = 'abc123'
|
||||||
|
@ -93,7 +95,7 @@ class HeartbeatTestCase(TestCase):
|
||||||
logging.disable(logging.NOTSET)
|
logging.disable(logging.NOTSET)
|
||||||
|
|
||||||
class Args(object):
|
class Args(object):
|
||||||
hidefilenames = ['.*']
|
hide_filenames = ['.*']
|
||||||
plugin = None
|
plugin = None
|
||||||
|
|
||||||
branch = 'abc123'
|
branch = 'abc123'
|
||||||
|
|
|
@ -69,7 +69,7 @@ class LoggingTestCase(utils.TestCase):
|
||||||
entity = 'tests/samples/codefiles/python.py'
|
entity = 'tests/samples/codefiles/python.py'
|
||||||
config = 'tests/samples/configs/good_config.cfg'
|
config = 'tests/samples/configs/good_config.cfg'
|
||||||
logfile = os.path.realpath(fh.name)
|
logfile = os.path.realpath(fh.name)
|
||||||
args = ['--file', entity, '--config', config, '--time', now, '--logfile', logfile]
|
args = ['--file', entity, '--config', config, '--time', now, '--log-file', logfile]
|
||||||
|
|
||||||
execute(args)
|
execute(args)
|
||||||
|
|
||||||
|
|
|
@ -163,7 +163,7 @@ class MainTestCase(utils.TestCase):
|
||||||
'dependencies': [],
|
'dependencies': [],
|
||||||
}
|
}
|
||||||
|
|
||||||
args = ['--file', entity, '--key', key, '--disableoffline',
|
args = ['--file', entity, '--key', key, '--disable-offline',
|
||||||
'--config', 'tests/samples/configs/good_config.cfg', '--time', now]
|
'--config', 'tests/samples/configs/good_config.cfg', '--time', now]
|
||||||
|
|
||||||
retval = execute(args)
|
retval = execute(args)
|
||||||
|
@ -244,7 +244,7 @@ class MainTestCase(utils.TestCase):
|
||||||
now = u(int(time.time()))
|
now = u(int(time.time()))
|
||||||
key = str(uuid.uuid4())
|
key = str(uuid.uuid4())
|
||||||
|
|
||||||
args = ['--file', entity, '--key', key, '--disableoffline',
|
args = ['--file', entity, '--key', key, '--disable-offline',
|
||||||
'--config', 'tests/samples/configs/good_config.cfg', '--time', now]
|
'--config', 'tests/samples/configs/good_config.cfg', '--time', now]
|
||||||
|
|
||||||
retval = execute(args)
|
retval = execute(args)
|
||||||
|
|
|
@ -25,7 +25,7 @@ class SessionCacheTestCase(utils.TestCase):
|
||||||
version = ''
|
version = ''
|
||||||
plugin = ''
|
plugin = ''
|
||||||
verbose = False
|
verbose = False
|
||||||
logfile = ''
|
log_file = ''
|
||||||
self.args = MockArgs()
|
self.args = MockArgs()
|
||||||
setup_logging(self.args, self.args.version)
|
setup_logging(self.args, self.args.version)
|
||||||
|
|
||||||
|
|
|
@ -103,12 +103,17 @@ def parse_arguments():
|
||||||
'auto-detected language')
|
'auto-detected language')
|
||||||
parser.add_argument('--hostname', dest='hostname', action=StoreWithoutQuotes, help='hostname of '+
|
parser.add_argument('--hostname', dest='hostname', action=StoreWithoutQuotes, help='hostname of '+
|
||||||
'current machine.')
|
'current machine.')
|
||||||
parser.add_argument('--disableoffline', dest='offline',
|
parser.add_argument('--disable-offline', dest='offline',
|
||||||
action='store_false',
|
action='store_false',
|
||||||
help='disables offline time logging instead of queuing logged time')
|
help='disables offline time logging instead of queuing logged time')
|
||||||
parser.add_argument('--hidefilenames', dest='hidefilenames',
|
parser.add_argument('--disableoffline', dest='offline_deprecated',
|
||||||
|
action='store_true', help=argparse.SUPPRESS)
|
||||||
|
parser.add_argument('--hide-filenames', dest='hide_filenames',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help='obfuscate filenames; will not send file names to api')
|
help='obfuscate filenames; will not send file names to api')
|
||||||
|
parser.add_argument('--hidefilenames', dest='hidefilenames',
|
||||||
|
action='store_true',
|
||||||
|
help=argparse.SUPPRESS)
|
||||||
parser.add_argument('--exclude', dest='exclude', action='append',
|
parser.add_argument('--exclude', dest='exclude', action='append',
|
||||||
help='filename patterns to exclude from logging; POSIX regex '+
|
help='filename patterns to exclude from logging; POSIX regex '+
|
||||||
'syntax; can be used more than once')
|
'syntax; can be used more than once')
|
||||||
|
@ -116,15 +121,24 @@ def parse_arguments():
|
||||||
help='filename patterns to log; when used in combination with '+
|
help='filename patterns to log; when used in combination with '+
|
||||||
'--exclude, files matching include will still be logged; '+
|
'--exclude, files matching include will still be logged; '+
|
||||||
'POSIX regex syntax; can be used more than once')
|
'POSIX regex syntax; can be used more than once')
|
||||||
|
parser.add_argument('--include-only-with-project-file',
|
||||||
|
dest='include_only_with_project_file',
|
||||||
|
action='store_true',
|
||||||
|
help='disables tracking folders unless they contain '+
|
||||||
|
'a .wakatime-project file; defaults to false')
|
||||||
parser.add_argument('--ignore', dest='ignore', action='append',
|
parser.add_argument('--ignore', dest='ignore', action='append',
|
||||||
help=argparse.SUPPRESS)
|
help=argparse.SUPPRESS)
|
||||||
parser.add_argument('--extra-heartbeats', dest='extra_heartbeats',
|
parser.add_argument('--extra-heartbeats', dest='extra_heartbeats',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help='reads extra heartbeats from STDIN as a JSON array until EOF')
|
help='reads extra heartbeats from STDIN as a JSON array until EOF')
|
||||||
parser.add_argument('--logfile', dest='logfile', action=StoreWithoutQuotes,
|
parser.add_argument('--log-file', dest='log_file', action=StoreWithoutQuotes,
|
||||||
help='defaults to ~/.wakatime.log')
|
help='defaults to ~/.wakatime.log')
|
||||||
parser.add_argument('--apiurl', dest='api_url', action=StoreWithoutQuotes,
|
parser.add_argument('--logfile', dest='logfile', action=StoreWithoutQuotes,
|
||||||
|
help=argparse.SUPPRESS)
|
||||||
|
parser.add_argument('--api-url', dest='api_url', action=StoreWithoutQuotes,
|
||||||
help='heartbeats api url; for debugging with a local server')
|
help='heartbeats api url; for debugging with a local server')
|
||||||
|
parser.add_argument('--apiurl', dest='apiurl', action=StoreWithoutQuotes,
|
||||||
|
help=argparse.SUPPRESS)
|
||||||
parser.add_argument('--timeout', dest='timeout', type=int, action=StoreWithoutQuotes,
|
parser.add_argument('--timeout', dest='timeout', type=int, action=StoreWithoutQuotes,
|
||||||
help='number of seconds to wait when sending heartbeats to api; '+
|
help='number of seconds to wait when sending heartbeats to api; '+
|
||||||
'defaults to 60 seconds')
|
'defaults to 60 seconds')
|
||||||
|
@ -194,6 +208,8 @@ def parse_arguments():
|
||||||
args.exclude.append(pattern)
|
args.exclude.append(pattern)
|
||||||
except TypeError: # pragma: nocover
|
except TypeError: # pragma: nocover
|
||||||
pass
|
pass
|
||||||
|
if not args.include_only_with_project_file and configs.has_option('settings', 'include_only_with_project_file'):
|
||||||
|
args.include_only_with_project_file = configs.get('settings', 'include_only_with_project_file')
|
||||||
if not args.include:
|
if not args.include:
|
||||||
args.include = []
|
args.include = []
|
||||||
if configs.has_option('settings', 'include'):
|
if configs.has_option('settings', 'include'):
|
||||||
|
@ -203,18 +219,26 @@ def parse_arguments():
|
||||||
args.include.append(pattern)
|
args.include.append(pattern)
|
||||||
except TypeError: # pragma: nocover
|
except TypeError: # pragma: nocover
|
||||||
pass
|
pass
|
||||||
if args.hidefilenames:
|
if not args.hide_filenames and args.hidefilenames:
|
||||||
args.hidefilenames = ['.*']
|
args.hide_filenames = args.hidefilenames
|
||||||
|
if args.hide_filenames:
|
||||||
|
args.hide_filenames = ['.*']
|
||||||
else:
|
else:
|
||||||
args.hidefilenames = []
|
args.hide_filenames = []
|
||||||
|
option = None
|
||||||
if configs.has_option('settings', 'hidefilenames'):
|
if configs.has_option('settings', 'hidefilenames'):
|
||||||
option = configs.get('settings', 'hidefilenames')
|
option = configs.get('settings', 'hidefilenames')
|
||||||
|
if configs.has_option('settings', 'hide_filenames'):
|
||||||
|
option = configs.get('settings', 'hide_filenames')
|
||||||
|
if option is not None:
|
||||||
if option.strip().lower() == 'true':
|
if option.strip().lower() == 'true':
|
||||||
args.hidefilenames = ['.*']
|
args.hide_filenames = ['.*']
|
||||||
elif option.strip().lower() != 'false':
|
elif option.strip().lower() != 'false':
|
||||||
for pattern in option.split("\n"):
|
for pattern in option.split("\n"):
|
||||||
if pattern.strip() != '':
|
if pattern.strip() != '':
|
||||||
args.hidefilenames.append(pattern)
|
args.hide_filenames.append(pattern)
|
||||||
|
if args.offline_deprecated:
|
||||||
|
args.offline = False
|
||||||
if args.offline and configs.has_option('settings', 'offline'):
|
if args.offline and configs.has_option('settings', 'offline'):
|
||||||
args.offline = configs.getboolean('settings', 'offline')
|
args.offline = configs.getboolean('settings', 'offline')
|
||||||
if not args.proxy and configs.has_option('settings', 'proxy'):
|
if not args.proxy and configs.has_option('settings', 'proxy'):
|
||||||
|
@ -235,11 +259,15 @@ def parse_arguments():
|
||||||
args.verbose = configs.getboolean('settings', 'verbose')
|
args.verbose = configs.getboolean('settings', 'verbose')
|
||||||
if not args.verbose and configs.has_option('settings', 'debug'):
|
if not args.verbose and configs.has_option('settings', 'debug'):
|
||||||
args.verbose = configs.getboolean('settings', 'debug')
|
args.verbose = configs.getboolean('settings', 'debug')
|
||||||
if not args.logfile and configs.has_option('settings', 'logfile'):
|
if not args.log_file and args.logfile:
|
||||||
args.logfile = configs.get('settings', 'logfile')
|
args.log_file = args.logfile
|
||||||
if not args.logfile and os.environ.get('WAKATIME_HOME'):
|
if not args.log_file and configs.has_option('settings', 'log_file'):
|
||||||
|
args.log_file = configs.get('settings', 'log_file')
|
||||||
|
if not args.log_file and os.environ.get('WAKATIME_HOME'):
|
||||||
home = os.environ.get('WAKATIME_HOME')
|
home = os.environ.get('WAKATIME_HOME')
|
||||||
args.logfile = os.path.join(os.path.expanduser(home), '.wakatime.log')
|
args.log_file = os.path.join(os.path.expanduser(home), '.wakatime.log')
|
||||||
|
if not args.api_url and args.apiurl:
|
||||||
|
args.api_url = args.apiurl
|
||||||
if not args.api_url and configs.has_option('settings', 'api_url'):
|
if not args.api_url and configs.has_option('settings', 'api_url'):
|
||||||
args.api_url = configs.get('settings', 'api_url')
|
args.api_url = configs.get('settings', 'api_url')
|
||||||
if not args.timeout and configs.has_option('settings', 'timeout'):
|
if not args.timeout and configs.has_option('settings', 'timeout'):
|
||||||
|
|
|
@ -14,7 +14,7 @@ import re
|
||||||
from .compat import u, json
|
from .compat import u, json
|
||||||
from .project import get_project_info
|
from .project import get_project_info
|
||||||
from .stats import get_file_stats
|
from .stats import get_file_stats
|
||||||
from .utils import get_user_agent, should_exclude, format_file_path
|
from .utils import get_user_agent, should_exclude, format_file_path, find_project_file
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger('WakaTime')
|
log = logging.getLogger('WakaTime')
|
||||||
|
@ -66,9 +66,12 @@ class Heartbeat(object):
|
||||||
return
|
return
|
||||||
if self.type == 'file':
|
if self.type == 'file':
|
||||||
self.entity = format_file_path(self.entity)
|
self.entity = format_file_path(self.entity)
|
||||||
if self.type == 'file' and (not self.entity or not os.path.isfile(self.entity)):
|
if not self.entity or not os.path.isfile(self.entity):
|
||||||
self.skip = u('File does not exist; ignoring this heartbeat.')
|
self.skip = u('File does not exist; ignoring this heartbeat.')
|
||||||
return
|
return
|
||||||
|
if self._excluded_by_missing_project_file():
|
||||||
|
self.skip = u('Skipping because missing .wakatime-project file in parent path.')
|
||||||
|
return
|
||||||
|
|
||||||
project, branch = get_project_info(configs, self, data)
|
project, branch = get_project_info(configs, self, data)
|
||||||
self.project = project
|
self.project = project
|
||||||
|
@ -103,7 +106,7 @@ class Heartbeat(object):
|
||||||
Returns a Heartbeat.
|
Returns a Heartbeat.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not self.args.hidefilenames:
|
if not self.args.hide_filenames:
|
||||||
return self
|
return self
|
||||||
|
|
||||||
if self.entity is None:
|
if self.entity is None:
|
||||||
|
@ -112,7 +115,7 @@ class Heartbeat(object):
|
||||||
if self.type != 'file':
|
if self.type != 'file':
|
||||||
return self
|
return self
|
||||||
|
|
||||||
for pattern in self.args.hidefilenames:
|
for pattern in self.args.hide_filenames:
|
||||||
try:
|
try:
|
||||||
compiled = re.compile(pattern, re.IGNORECASE)
|
compiled = re.compile(pattern, re.IGNORECASE)
|
||||||
if compiled.search(self.entity):
|
if compiled.search(self.entity):
|
||||||
|
@ -183,6 +186,11 @@ class Heartbeat(object):
|
||||||
def _excluded_by_pattern(self):
|
def _excluded_by_pattern(self):
|
||||||
return should_exclude(self.entity, self.args.include, self.args.exclude)
|
return should_exclude(self.entity, self.args.include, self.args.exclude)
|
||||||
|
|
||||||
|
def _excluded_by_missing_project_file(self):
|
||||||
|
if not self.args.include_only_with_project_file:
|
||||||
|
return False
|
||||||
|
return find_project_file(self.entity) is None
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return self.json()
|
return self.json()
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@ def setup_logging(args, version):
|
||||||
for handler in logger.handlers:
|
for handler in logger.handlers:
|
||||||
logger.removeHandler(handler)
|
logger.removeHandler(handler)
|
||||||
set_log_level(logger, args)
|
set_log_level(logger, args)
|
||||||
logfile = args.logfile
|
logfile = args.log_file
|
||||||
if not logfile:
|
if not logfile:
|
||||||
logfile = '~/.wakatime.log'
|
logfile = '~/.wakatime.log'
|
||||||
handler = logging.FileHandler(os.path.expanduser(logfile))
|
handler = logging.FileHandler(os.path.expanduser(logfile))
|
||||||
|
|
|
@ -12,11 +12,11 @@
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from .base import BaseProject
|
from .base import BaseProject
|
||||||
from ..compat import u, open
|
from ..compat import u, open
|
||||||
|
from ..utils import find_project_file
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger('WakaTime')
|
log = logging.getLogger('WakaTime')
|
||||||
|
@ -25,7 +25,7 @@ log = logging.getLogger('WakaTime')
|
||||||
class ProjectFile(BaseProject):
|
class ProjectFile(BaseProject):
|
||||||
|
|
||||||
def process(self):
|
def process(self):
|
||||||
self.config = self._find_config(self.path)
|
self.config = find_project_file(self.path)
|
||||||
self._project_name = None
|
self._project_name = None
|
||||||
self._project_branch = None
|
self._project_branch = None
|
||||||
|
|
||||||
|
@ -33,13 +33,13 @@ class ProjectFile(BaseProject):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open(self.config, 'r', encoding='utf-8') as fh:
|
with open(self.config, 'r', encoding='utf-8') as fh:
|
||||||
self._project_name = u(fh.readline().strip())
|
self._project_name = u(fh.readline().strip()) or None
|
||||||
self._project_branch = u(fh.readline().strip())
|
self._project_branch = u(fh.readline().strip()) or None
|
||||||
except UnicodeDecodeError: # pragma: nocover
|
except UnicodeDecodeError: # pragma: nocover
|
||||||
try:
|
try:
|
||||||
with open(self.config, 'r', encoding=sys.getfilesystemencoding()) as fh:
|
with open(self.config, 'r', encoding=sys.getfilesystemencoding()) as fh:
|
||||||
self._project_name = u(fh.readline().strip())
|
self._project_name = u(fh.readline().strip()) or None
|
||||||
self._project_branch = u(fh.readline().strip())
|
self._project_branch = u(fh.readline().strip()) or None
|
||||||
except:
|
except:
|
||||||
log.traceback(logging.WARNING)
|
log.traceback(logging.WARNING)
|
||||||
except IOError: # pragma: nocover
|
except IOError: # pragma: nocover
|
||||||
|
@ -53,14 +53,3 @@ class ProjectFile(BaseProject):
|
||||||
|
|
||||||
def branch(self):
|
def branch(self):
|
||||||
return self._project_branch
|
return self._project_branch
|
||||||
|
|
||||||
def _find_config(self, path):
|
|
||||||
path = os.path.realpath(path)
|
|
||||||
if os.path.isfile(path):
|
|
||||||
path = os.path.split(path)[0]
|
|
||||||
if os.path.isfile(os.path.join(path, '.wakatime-project')):
|
|
||||||
return os.path.join(path, '.wakatime-project')
|
|
||||||
split_path = os.path.split(path)
|
|
||||||
if split_path[1] == '':
|
|
||||||
return None
|
|
||||||
return self._find_config(split_path[0])
|
|
||||||
|
|
|
@ -82,3 +82,15 @@ def format_file_path(filepath):
|
||||||
|
|
||||||
def get_hostname(args):
|
def get_hostname(args):
|
||||||
return args.hostname or socket.gethostname()
|
return args.hostname or socket.gethostname()
|
||||||
|
|
||||||
|
|
||||||
|
def find_project_file(path):
|
||||||
|
path = os.path.realpath(path)
|
||||||
|
if os.path.isfile(path):
|
||||||
|
path = os.path.split(path)[0]
|
||||||
|
if os.path.isfile(os.path.join(path, '.wakatime-project')):
|
||||||
|
return os.path.join(path, '.wakatime-project')
|
||||||
|
split_path = os.path.split(path)
|
||||||
|
if split_path[1] == '':
|
||||||
|
return None
|
||||||
|
return find_project_file(split_path[0])
|
||||||
|
|
Loading…
Reference in a new issue