new --entitytype command line arg to replace --notfile

This commit is contained in:
Alan Hamlett 2015-08-29 16:16:14 -07:00
parent 48943519ae
commit 92948386fa
10 changed files with 77 additions and 67 deletions

View file

@ -1,6 +1,6 @@
usage: wakatime [-h] --file file [--key KEY] [--write] [--plugin PLUGIN]
[--time time] [--lineno LINENO] [--cursorpos CURSORPOS]
[--notfile] [--proxy PROXY] [--project PROJECT]
[--entitytype ENTITY_TYPE] [--proxy PROXY] [--project PROJECT]
[--alternate-project ALTERNATE_PROJECT] [--hostname HOSTNAME]
[--disableoffline] [--hidefilenames] [--exclude EXCLUDE]
[--include INCLUDE] [--logfile LOGFILE] [--apiurl API_URL]
@ -22,9 +22,9 @@ optional arguments:
--lineno LINENO optional line number; current line being edited
--cursorpos CURSORPOS
optional cursor position in the current file
--notfile when set, will accept any value for the file. for
example, a domain name or other item you want to log
time towards.
--entitytype ENTITY_TYPE
entity type for this heartbeat. can be one of "file",
"url", or "domain"; defaults to file.
--proxy PROXY optional https proxy url; for example:
https://user:pass@localhost:8080
--project PROJECT optional project name

View file

@ -1,6 +1,6 @@
usage: wakatime [-h] --file file [--key KEY] [--write] [--plugin PLUGIN]
[--time time] [--lineno LINENO] [--cursorpos CURSORPOS]
[--notfile] [--proxy PROXY] [--project PROJECT]
[--entitytype ENTITY_TYPE] [--proxy PROXY] [--project PROJECT]
[--alternate-project ALTERNATE_PROJECT] [--hostname HOSTNAME]
[--disableoffline] [--hidefilenames] [--exclude EXCLUDE]
[--include INCLUDE] [--logfile LOGFILE] [--apiurl API_URL]

View file

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
from wakatime.base import main
from wakatime.main import execute
from wakatime.packages import requests
import os
@ -38,7 +38,7 @@ class LanguagesTestCase(utils.TestCase):
args = ['--file', entity, '--config', config, '--time', now]
retval = main(args)
retval = execute(args)
self.assertEquals(retval, 102)
self.assertEquals(sys.stdout.getvalue(), '')
self.assertEquals(sys.stderr.getvalue(), '')
@ -48,16 +48,19 @@ class LanguagesTestCase(utils.TestCase):
self.patched['wakatime.session_cache.SessionCache.save'].assert_not_called()
heartbeat = {
'language': 'Python',
'language': u('Python'),
'lines': 26,
'entity': os.path.abspath(entity),
'project': os.path.basename(os.path.abspath('.')),
'dependencies': ['wakatime', 'os', 'mock', 'simplejson', 'django'],
'project': u(os.path.basename(os.path.abspath('.'))),
'dependencies': ANY,
'branch': os.environ.get('TRAVIS_COMMIT', ANY),
'time': float(now),
'type': 'file',
}
stats = '{"cursorpos": null, "dependencies": ["wakatime", "os", "mock", "simplejson", "django"], "lines": 26, "lineno": null, "language": "Python"}'
stats = ANY
expected_dependencies = ['wakatime', 'mock', 'django', 'simplejson', 'os']
self.patched['wakatime.offlinequeue.Queue.push'].assert_called_once_with(heartbeat, stats, None)
for dep in expected_dependencies:
self.assertIn(dep, self.patched['wakatime.offlinequeue.Queue.push'].call_args[0][0]['dependencies'])
self.patched['wakatime.offlinequeue.Queue.pop'].assert_not_called()

View file

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
from wakatime.base import main
from wakatime.main import execute
from wakatime.packages import requests
import os
@ -30,7 +30,7 @@ class BaseTestCase(utils.TestCase):
def test_help_contents(self):
args = ['--help']
with self.assertRaises(SystemExit):
main(args)
execute(args)
expected_stdout = open('tests/samples/output/test_help_contents').read()
self.assertEquals(sys.stdout.getvalue(), expected_stdout)
self.assertEquals(sys.stderr.getvalue(), '')
@ -45,7 +45,7 @@ class BaseTestCase(utils.TestCase):
args = ['--file', 'tests/samples/twolinefile.txt', '--key', '123', '--config', 'tests/samples/sample.cfg']
retval = main(args)
retval = execute(args)
self.assertEquals(retval, 0)
self.assertEquals(sys.stdout.getvalue(), '')
self.assertEquals(sys.stderr.getvalue(), '')
@ -60,7 +60,7 @@ class BaseTestCase(utils.TestCase):
def test_missing_config_file(self):
args = ['--file', 'tests/samples/emptyfile.txt', '--config', 'foo']
with self.assertRaises(SystemExit):
main(args)
execute(args)
expected_stdout = u("Error: Could not read from config file foo\n")
expected_stderr = open('tests/samples/output/test_missing_config_file').read()
self.assertEquals(sys.stdout.getvalue(), expected_stdout)
@ -74,7 +74,7 @@ class BaseTestCase(utils.TestCase):
self.patched['wakatime.packages.requests.adapters.HTTPAdapter.send'].return_value = response
args = ['--file', 'tests/samples/emptyfile.txt', '--config', 'tests/samples/sample.cfg']
retval = main(args)
retval = execute(args)
self.assertEquals(retval, 0)
self.assertEquals(sys.stdout.getvalue(), '')
self.assertEquals(sys.stderr.getvalue(), '')
@ -88,7 +88,7 @@ class BaseTestCase(utils.TestCase):
def test_bad_config_file(self):
args = ['--file', 'tests/samples/emptyfile.txt', '--config', 'tests/samples/bad_config.cfg']
retval = main(args)
retval = execute(args)
self.assertEquals(retval, 103)
self.assertIn('ParsingError', sys.stdout.getvalue())
self.assertEquals(sys.stderr.getvalue(), '')
@ -108,7 +108,7 @@ class BaseTestCase(utils.TestCase):
args = ['--file', entity, '--key', '123', '--config', config, '--time', now]
retval = main(args)
retval = execute(args)
self.assertEquals(retval, 102)
self.assertEquals(sys.stdout.getvalue(), '')
self.assertEquals(sys.stderr.getvalue(), '')
@ -126,7 +126,7 @@ class BaseTestCase(utils.TestCase):
'time': float(now),
'type': 'file',
}
stats = '{"cursorpos": null, "dependencies": [], "lines": 2, "lineno": null, "language": "Text only"}'
stats = ANY
self.patched['wakatime.offlinequeue.Queue.push'].assert_called_once_with(heartbeat, stats, None)
self.patched['wakatime.offlinequeue.Queue.pop'].assert_not_called()
@ -142,7 +142,7 @@ class BaseTestCase(utils.TestCase):
args = ['--file', entity, '--key', '123', '--config', config, '--time', now]
retval = main(args)
retval = execute(args)
self.assertEquals(retval, 102)
self.assertEquals(sys.stdout.getvalue(), '')
self.assertEquals(sys.stderr.getvalue(), '')
@ -160,7 +160,7 @@ class BaseTestCase(utils.TestCase):
'time': float(now),
'type': 'file',
}
stats = '{"cursorpos": null, "dependencies": [], "lines": 2, "lineno": null, "language": "Text only"}'
stats = ANY
self.patched['wakatime.offlinequeue.Queue.push'].assert_called_once_with(heartbeat, stats, None)
self.patched['wakatime.offlinequeue.Queue.pop'].assert_not_called()
@ -176,7 +176,7 @@ class BaseTestCase(utils.TestCase):
'--config', 'tests/samples/paranoid.cfg', '--time', now]
retval = main(args)
retval = execute(args)
self.assertEquals(retval, 102)
self.assertEquals(sys.stdout.getvalue(), '')
self.assertEquals(sys.stderr.getvalue(), '')
@ -194,7 +194,7 @@ class BaseTestCase(utils.TestCase):
'time': float(now),
'type': 'file',
}
stats = '{"cursorpos": null, "dependencies": [], "lines": 2, "lineno": null, "language": "Text only"}'
stats = ANY
self.patched['wakatime.offlinequeue.Queue.push'].assert_called_once_with(heartbeat, stats, None)
self.patched['wakatime.offlinequeue.Queue.pop'].assert_not_called()
@ -210,7 +210,7 @@ class BaseTestCase(utils.TestCase):
'--config', 'tests/samples/paranoid.cfg', '--time', now]
retval = main(args)
retval = execute(args)
self.assertEquals(retval, 102)
self.assertEquals(sys.stdout.getvalue(), '')
self.assertEquals(sys.stderr.getvalue(), '')
@ -233,7 +233,7 @@ class BaseTestCase(utils.TestCase):
args = ['--file', entity, '--alternate-project', 'xyz', '--config', config, '--time', now]
retval = main(args)
retval = execute(args)
self.assertEquals(retval, 102)
self.assertEquals(sys.stdout.getvalue(), '')
self.assertEquals(sys.stderr.getvalue(), '')
@ -251,7 +251,7 @@ class BaseTestCase(utils.TestCase):
'time': float(now),
'type': 'file',
}
stats = '{"cursorpos": null, "dependencies": [], "lines": 2, "lineno": null, "language": "Text only"}'
stats = ANY
self.patched['wakatime.offlinequeue.Queue.push'].assert_called_once_with(heartbeat, stats, None)
self.patched['wakatime.offlinequeue.Queue.pop'].assert_not_called()
@ -267,7 +267,7 @@ class BaseTestCase(utils.TestCase):
args = ['--file', entity, '--project', 'xyz', '--config', config, '--time', now]
retval = main(args)
retval = execute(args)
self.assertEquals(retval, 102)
self.assertEquals(sys.stdout.getvalue(), '')
self.assertEquals(sys.stderr.getvalue(), '')
@ -285,7 +285,7 @@ class BaseTestCase(utils.TestCase):
'time': float(now),
'type': 'file',
}
stats = '{"cursorpos": null, "dependencies": [], "lines": 2, "lineno": null, "language": "Text only"}'
stats = ANY
self.patched['wakatime.offlinequeue.Queue.push'].assert_called_once_with(heartbeat, stats, None)
self.patched['wakatime.offlinequeue.Queue.pop'].assert_not_called()

View file

@ -14,4 +14,4 @@
__all__ = ['main']
from .base import main
from .main import execute

View file

@ -32,4 +32,4 @@ except (TypeError, ImportError):
if __name__ == '__main__':
sys.exit(wakatime.main(sys.argv[1:]))
sys.exit(wakatime.execute(sys.argv[1:]))

View file

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
"""
wakatime.base
wakatime.main
~~~~~~~~~~~~~
wakatime module entry point.
@ -109,9 +109,9 @@ def parseArguments():
help='optional line number; current line being edited')
parser.add_argument('--cursorpos', dest='cursorpos',
help='optional cursor position in the current file')
parser.add_argument('--notfile', dest='notfile', action='store_true',
help='when set, will accept any value for the file. for example, '+
'a domain name or other item you want to log time towards.')
parser.add_argument('--entitytype', dest='entity_type',
help='entity type for this heartbeat. can be one of "file", '+
'"url", or "domain"; defaults to file.')
parser.add_argument('--proxy', dest='proxy',
help='optional https proxy url; for example: '+
'https://user:pass@localhost:8080')
@ -168,6 +168,8 @@ def parseArguments():
args.key = default_key
else:
parser.error('Missing api key')
if not args.entity_type:
args.entity_type = 'file'
if not args.exclude:
args.exclude = []
if configs.has_option('settings', 'ignore'):
@ -263,7 +265,7 @@ def get_user_agent(plugin):
def send_heartbeat(project=None, branch=None, hostname=None, stats={}, key=None, targetFile=None,
timestamp=None, isWrite=None, plugin=None, offline=None, notfile=False,
timestamp=None, isWrite=None, plugin=None, offline=None, entity_type='file',
hidefilenames=None, proxy=None, api_url=None, **kwargs):
"""Sends heartbeat as POST request to WakaTime api server.
"""
@ -274,9 +276,9 @@ def send_heartbeat(project=None, branch=None, hostname=None, stats={}, key=None,
data = {
'time': timestamp,
'entity': targetFile,
'type': 'file',
'type': entity_type,
}
if hidefilenames and targetFile is not None and not notfile:
if hidefilenames and targetFile is not None and entity_type == 'file':
extension = u(os.path.splitext(data['entity'])[1])
data['entity'] = u('HIDDEN{0}').format(extension)
if stats.get('lines'):
@ -379,7 +381,7 @@ def send_heartbeat(project=None, branch=None, hostname=None, stats={}, key=None,
return False
def main(argv):
def execute(argv):
sys.argv = ['wakatime'] + argv
args, configs = parseArguments()
@ -395,14 +397,15 @@ def main(argv):
))
return 0
if os.path.isfile(args.targetFile) or args.notfile:
if args.entity_type != 'file' or os.path.isfile(args.targetFile):
stats = get_file_stats(args.targetFile, notfile=args.notfile,
stats = get_file_stats(args.targetFile, entity_type=args.entity_type,
lineno=args.lineno, cursorpos=args.cursorpos)
project, branch = None, None
if not args.notfile:
project, branch = get_project_info(configs=configs, args=args)
project = args.project or args.alternate_project
branch = None
if args.entity_type == 'file':
project, branch = get_project_info(configs, args)
kwargs = vars(args)
kwargs['project'] = project
@ -428,7 +431,7 @@ def main(argv):
plugin=heartbeat['plugin'],
offline=args.offline,
hidefilenames=args.hidefilenames,
notfile=args.notfile,
entity_type=heartbeat['type'],
proxy=args.proxy,
api_url=args.api_url,
)

View file

@ -28,13 +28,15 @@ log = logging.getLogger('WakaTime')
class Queue(object):
DB_FILE = os.path.join(os.path.expanduser('~'), '.wakatime.db')
db_file = os.path.join(os.path.expanduser('~'), '.wakatime.db')
table_name = 'heartbeat_1'
def connect(self):
conn = sqlite3.connect(self.DB_FILE)
conn = sqlite3.connect(self.db_file)
c = conn.cursor()
c.execute('''CREATE TABLE IF NOT EXISTS heartbeat (
file text,
c.execute('''CREATE TABLE IF NOT EXISTS {0} (
entity text,
type text,
time real,
project text,
branch text,
@ -42,7 +44,7 @@ class Queue(object):
stats text,
misc text,
plugin text)
''')
'''.format(self.table_name))
return (conn, c)
@ -52,7 +54,8 @@ class Queue(object):
try:
conn, c = self.connect()
heartbeat = {
'file': u(data.get('entity')),
'entity': u(data.get('entity')),
'type': u(data.get('type')),
'time': data.get('time'),
'project': u(data.get('project')),
'branch': u(data.get('branch')),
@ -61,7 +64,7 @@ class Queue(object):
'misc': u(misc),
'plugin': u(plugin),
}
c.execute('INSERT INTO heartbeat VALUES (:file,:time,:project,:branch,:is_write,:stats,:misc,:plugin)', heartbeat)
c.execute('INSERT INTO {0} VALUES (:entity,:type,:time,:project,:branch,:is_write,:stats,:misc,:plugin)'.format(self.table_name), heartbeat)
conn.commit()
conn.close()
except sqlite3.Error:
@ -83,13 +86,13 @@ class Queue(object):
while loop and tries > -1:
try:
c.execute('BEGIN IMMEDIATE')
c.execute('SELECT * FROM heartbeat LIMIT 1')
c.execute('SELECT * FROM {0} LIMIT 1'.format(self.table_name))
row = c.fetchone()
if row is not None:
values = []
clauses = []
index = 0
for row_name in ['file', 'time', 'project', 'branch', 'is_write']:
for row_name in ['entity', 'type', 'time', 'project', 'branch', 'is_write']:
if row[index] is not None:
clauses.append('{0}=?'.format(row_name))
values.append(row[index])
@ -97,20 +100,21 @@ class Queue(object):
clauses.append('{0} IS NULL'.format(row_name))
index += 1
if len(values) > 0:
c.execute('DELETE FROM heartbeat WHERE {0}'.format(' AND '.join(clauses)), values)
c.execute('DELETE FROM {0} WHERE {1}'.format(self.table_name, ' AND '.join(clauses)), values)
else:
c.execute('DELETE FROM heartbeat WHERE {0}'.format(' AND '.join(clauses)))
c.execute('DELETE FROM {0} WHERE {1}'.format(self.table_name, ' AND '.join(clauses)))
conn.commit()
if row is not None:
heartbeat = {
'file': row[0],
'time': row[1],
'project': row[2],
'branch': row[3],
'is_write': True if row[4] is 1 else False,
'stats': row[5],
'misc': row[6],
'plugin': row[7],
'entity': row[0],
'type': row[1],
'time': row[2],
'project': row[3],
'branch': row[4],
'is_write': True if row[5] is 1 else False,
'stats': row[6],
'misc': row[7],
'plugin': row[8],
}
loop = False
except sqlite3.Error:

View file

@ -33,7 +33,7 @@ REV_CONTROL_PLUGINS = [
]
def get_project_info(configs=None, args=None):
def get_project_info(configs, args):
"""Find the current project and branch.
First looks for a .wakatime-project file. Second, uses the --project arg.
@ -52,7 +52,7 @@ def get_project_info(configs=None, args=None):
project = plugin_cls(args.targetFile, configs=plugin_configs)
if project.process():
project_name = project.name()
project_name = project_name or project.name()
branch_name = project.branch()
break

View file

@ -153,8 +153,8 @@ def number_lines_in_file(file_name):
return lines
def get_file_stats(file_name, notfile=False, lineno=None, cursorpos=None):
if notfile:
def get_file_stats(file_name, entity_type='file', lineno=None, cursorpos=None):
if entity_type != 'file':
stats = {
'language': None,
'dependencies': [],