forked from luna/vim-rana-local
upgrade wakatime cli to v4.1.4
This commit is contained in:
parent
02277aca99
commit
1d1c59dbe1
8 changed files with 80 additions and 61 deletions
|
@ -1,7 +1,7 @@
|
||||||
__title__ = 'wakatime'
|
__title__ = 'wakatime'
|
||||||
__description__ = 'Common interface to the WakaTime api.'
|
__description__ = 'Common interface to the WakaTime api.'
|
||||||
__url__ = 'https://github.com/wakatime/wakatime'
|
__url__ = 'https://github.com/wakatime/wakatime'
|
||||||
__version_info__ = ('4', '1', '3')
|
__version_info__ = ('4', '1', '4')
|
||||||
__version__ = '.'.join(__version_info__)
|
__version__ = '.'.join(__version_info__)
|
||||||
__author__ = 'Alan Hamlett'
|
__author__ = 'Alan Hamlett'
|
||||||
__author_email__ = 'alan@wakatime.com'
|
__author_email__ = 'alan@wakatime.com'
|
||||||
|
|
|
@ -14,4 +14,4 @@
|
||||||
__all__ = ['main']
|
__all__ = ['main']
|
||||||
|
|
||||||
|
|
||||||
from .base import main
|
from .main import execute
|
||||||
|
|
|
@ -32,4 +32,4 @@ except (TypeError, ImportError):
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
sys.exit(wakatime.main(sys.argv[1:]))
|
sys.exit(wakatime.execute(sys.argv[1:]))
|
||||||
|
|
|
@ -40,11 +40,11 @@ class CustomEncoder(json.JSONEncoder):
|
||||||
|
|
||||||
class JsonFormatter(logging.Formatter):
|
class JsonFormatter(logging.Formatter):
|
||||||
|
|
||||||
def setup(self, timestamp, isWrite, targetFile, version, plugin, verbose,
|
def setup(self, timestamp, isWrite, entity, version, plugin, verbose,
|
||||||
warnings=False):
|
warnings=False):
|
||||||
self.timestamp = timestamp
|
self.timestamp = timestamp
|
||||||
self.isWrite = isWrite
|
self.isWrite = isWrite
|
||||||
self.targetFile = targetFile
|
self.entity = entity
|
||||||
self.version = version
|
self.version = version
|
||||||
self.plugin = plugin
|
self.plugin = plugin
|
||||||
self.verbose = verbose
|
self.verbose = verbose
|
||||||
|
@ -61,7 +61,7 @@ class JsonFormatter(logging.Formatter):
|
||||||
data['caller'] = record.pathname
|
data['caller'] = record.pathname
|
||||||
data['lineno'] = record.lineno
|
data['lineno'] = record.lineno
|
||||||
data['isWrite'] = self.isWrite
|
data['isWrite'] = self.isWrite
|
||||||
data['file'] = self.targetFile
|
data['file'] = self.entity
|
||||||
if not self.isWrite:
|
if not self.isWrite:
|
||||||
del data['isWrite']
|
del data['isWrite']
|
||||||
data['level'] = record.levelname
|
data['level'] = record.levelname
|
||||||
|
@ -89,7 +89,7 @@ def setup_logging(args, version):
|
||||||
formatter.setup(
|
formatter.setup(
|
||||||
timestamp=args.timestamp,
|
timestamp=args.timestamp,
|
||||||
isWrite=args.isWrite,
|
isWrite=args.isWrite,
|
||||||
targetFile=args.targetFile,
|
entity=args.entity,
|
||||||
version=version,
|
version=version,
|
||||||
plugin=args.plugin,
|
plugin=args.plugin,
|
||||||
verbose=args.verbose,
|
verbose=args.verbose,
|
||||||
|
@ -104,7 +104,7 @@ def setup_logging(args, version):
|
||||||
formatter.setup(
|
formatter.setup(
|
||||||
timestamp=args.timestamp,
|
timestamp=args.timestamp,
|
||||||
isWrite=args.isWrite,
|
isWrite=args.isWrite,
|
||||||
targetFile=args.targetFile,
|
entity=args.entity,
|
||||||
version=version,
|
version=version,
|
||||||
plugin=args.plugin,
|
plugin=args.plugin,
|
||||||
verbose=args.verbose,
|
verbose=args.verbose,
|
||||||
|
@ -116,7 +116,7 @@ def setup_logging(args, version):
|
||||||
warnings_formatter.setup(
|
warnings_formatter.setup(
|
||||||
timestamp=args.timestamp,
|
timestamp=args.timestamp,
|
||||||
isWrite=args.isWrite,
|
isWrite=args.isWrite,
|
||||||
targetFile=args.targetFile,
|
entity=args.entity,
|
||||||
version=version,
|
version=version,
|
||||||
plugin=args.plugin,
|
plugin=args.plugin,
|
||||||
verbose=args.verbose,
|
verbose=args.verbose,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""
|
"""
|
||||||
wakatime.base
|
wakatime.main
|
||||||
~~~~~~~~~~~~~
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
wakatime module entry point.
|
wakatime module entry point.
|
||||||
|
@ -53,7 +53,11 @@ log = logging.getLogger('WakaTime')
|
||||||
class FileAction(argparse.Action):
|
class FileAction(argparse.Action):
|
||||||
|
|
||||||
def __call__(self, parser, namespace, values, option_string=None):
|
def __call__(self, parser, namespace, values, option_string=None):
|
||||||
values = os.path.realpath(values)
|
try:
|
||||||
|
if os.path.isfile(values):
|
||||||
|
values = os.path.realpath(values)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
setattr(namespace, self.dest, values)
|
setattr(namespace, self.dest, values)
|
||||||
|
|
||||||
|
|
||||||
|
@ -88,9 +92,12 @@ def parseArguments():
|
||||||
# define supported command line arguments
|
# define supported command line arguments
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
description='Common interface for the WakaTime api.')
|
description='Common interface for the WakaTime api.')
|
||||||
parser.add_argument('--file', dest='targetFile', metavar='file',
|
parser.add_argument('--entity', dest='entity', metavar='FILE',
|
||||||
action=FileAction, required=True,
|
action=FileAction,
|
||||||
help='absolute path to file for current heartbeat')
|
help='absolute path to file for the heartbeat; can also be a '+
|
||||||
|
'url, domain, or app when --entitytype is not file')
|
||||||
|
parser.add_argument('--file', dest='file', action=FileAction,
|
||||||
|
help=argparse.SUPPRESS)
|
||||||
parser.add_argument('--key', dest='key',
|
parser.add_argument('--key', dest='key',
|
||||||
help='your wakatime api key; uses api_key from '+
|
help='your wakatime api key; uses api_key from '+
|
||||||
'~/.wakatime.conf by default')
|
'~/.wakatime.conf by default')
|
||||||
|
@ -109,9 +116,9 @@ def parseArguments():
|
||||||
help='optional line number; current line being edited')
|
help='optional line number; current line being edited')
|
||||||
parser.add_argument('--cursorpos', dest='cursorpos',
|
parser.add_argument('--cursorpos', dest='cursorpos',
|
||||||
help='optional cursor position in the current file')
|
help='optional cursor position in the current file')
|
||||||
parser.add_argument('--notfile', dest='notfile', action='store_true',
|
parser.add_argument('--entitytype', dest='entity_type',
|
||||||
help='when set, will accept any value for the file. for example, '+
|
help='entity type for this heartbeat. can be one of "file", '+
|
||||||
'a domain name or other item you want to log time towards.')
|
'"url", "domain", or "app"; defaults to file.')
|
||||||
parser.add_argument('--proxy', dest='proxy',
|
parser.add_argument('--proxy', dest='proxy',
|
||||||
help='optional https proxy url; for example: '+
|
help='optional https proxy url; for example: '+
|
||||||
'https://user:pass@localhost:8080')
|
'https://user:pass@localhost:8080')
|
||||||
|
@ -168,6 +175,13 @@ def parseArguments():
|
||||||
args.key = default_key
|
args.key = default_key
|
||||||
else:
|
else:
|
||||||
parser.error('Missing api key')
|
parser.error('Missing api key')
|
||||||
|
if not args.entity_type:
|
||||||
|
args.entity_type = 'file'
|
||||||
|
if not args.entity:
|
||||||
|
if args.file:
|
||||||
|
args.entity = args.file
|
||||||
|
else:
|
||||||
|
parser.error('argument --entity is required')
|
||||||
if not args.exclude:
|
if not args.exclude:
|
||||||
args.exclude = []
|
args.exclude = []
|
||||||
if configs.has_option('settings', 'ignore'):
|
if configs.has_option('settings', 'ignore'):
|
||||||
|
@ -211,13 +225,13 @@ def parseArguments():
|
||||||
return args, configs
|
return args, configs
|
||||||
|
|
||||||
|
|
||||||
def should_exclude(fileName, include, exclude):
|
def should_exclude(entity, include, exclude):
|
||||||
if fileName is not None and fileName.strip() != '':
|
if entity is not None and entity.strip() != '':
|
||||||
try:
|
try:
|
||||||
for pattern in include:
|
for pattern in include:
|
||||||
try:
|
try:
|
||||||
compiled = re.compile(pattern, re.IGNORECASE)
|
compiled = re.compile(pattern, re.IGNORECASE)
|
||||||
if compiled.search(fileName):
|
if compiled.search(entity):
|
||||||
return False
|
return False
|
||||||
except re.error as ex:
|
except re.error as ex:
|
||||||
log.warning(u('Regex error ({msg}) for include pattern: {pattern}').format(
|
log.warning(u('Regex error ({msg}) for include pattern: {pattern}').format(
|
||||||
|
@ -230,7 +244,7 @@ def should_exclude(fileName, include, exclude):
|
||||||
for pattern in exclude:
|
for pattern in exclude:
|
||||||
try:
|
try:
|
||||||
compiled = re.compile(pattern, re.IGNORECASE)
|
compiled = re.compile(pattern, re.IGNORECASE)
|
||||||
if compiled.search(fileName):
|
if compiled.search(entity):
|
||||||
return pattern
|
return pattern
|
||||||
except re.error as ex:
|
except re.error as ex:
|
||||||
log.warning(u('Regex error ({msg}) for exclude pattern: {pattern}').format(
|
log.warning(u('Regex error ({msg}) for exclude pattern: {pattern}').format(
|
||||||
|
@ -262,8 +276,8 @@ def get_user_agent(plugin):
|
||||||
return user_agent
|
return user_agent
|
||||||
|
|
||||||
|
|
||||||
def send_heartbeat(project=None, branch=None, hostname=None, stats={}, key=None, targetFile=None,
|
def send_heartbeat(project=None, branch=None, hostname=None, stats={}, key=None, entity=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):
|
hidefilenames=None, proxy=None, api_url=None, **kwargs):
|
||||||
"""Sends heartbeat as POST request to WakaTime api server.
|
"""Sends heartbeat as POST request to WakaTime api server.
|
||||||
"""
|
"""
|
||||||
|
@ -273,10 +287,10 @@ def send_heartbeat(project=None, branch=None, hostname=None, stats={}, key=None,
|
||||||
log.debug('Sending heartbeat to api at %s' % api_url)
|
log.debug('Sending heartbeat to api at %s' % api_url)
|
||||||
data = {
|
data = {
|
||||||
'time': timestamp,
|
'time': timestamp,
|
||||||
'entity': targetFile,
|
'entity': entity,
|
||||||
'type': 'file',
|
'type': entity_type,
|
||||||
}
|
}
|
||||||
if hidefilenames and targetFile is not None and not notfile:
|
if hidefilenames and entity is not None and entity_type == 'file':
|
||||||
extension = u(os.path.splitext(data['entity'])[1])
|
extension = u(os.path.splitext(data['entity'])[1])
|
||||||
data['entity'] = u('HIDDEN{0}').format(extension)
|
data['entity'] = u('HIDDEN{0}').format(extension)
|
||||||
if stats.get('lines'):
|
if stats.get('lines'):
|
||||||
|
@ -379,7 +393,7 @@ def send_heartbeat(project=None, branch=None, hostname=None, stats={}, key=None,
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def main(argv):
|
def execute(argv):
|
||||||
sys.argv = ['wakatime'] + argv
|
sys.argv = ['wakatime'] + argv
|
||||||
|
|
||||||
args, configs = parseArguments()
|
args, configs = parseArguments()
|
||||||
|
@ -388,21 +402,22 @@ def main(argv):
|
||||||
|
|
||||||
setup_logging(args, __version__)
|
setup_logging(args, __version__)
|
||||||
|
|
||||||
exclude = should_exclude(args.targetFile, args.include, args.exclude)
|
exclude = should_exclude(args.entity, args.include, args.exclude)
|
||||||
if exclude is not False:
|
if exclude is not False:
|
||||||
log.debug(u('File not logged because matches exclude pattern: {pattern}').format(
|
log.debug(u('Skipping because matches exclude pattern: {pattern}').format(
|
||||||
pattern=u(exclude),
|
pattern=u(exclude),
|
||||||
))
|
))
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
if os.path.isfile(args.targetFile) or args.notfile:
|
if args.entity_type != 'file' or os.path.isfile(args.entity):
|
||||||
|
|
||||||
stats = get_file_stats(args.targetFile, notfile=args.notfile,
|
stats = get_file_stats(args.entity, entity_type=args.entity_type,
|
||||||
lineno=args.lineno, cursorpos=args.cursorpos)
|
lineno=args.lineno, cursorpos=args.cursorpos)
|
||||||
|
|
||||||
project, branch = None, None
|
project = args.project or args.alternate_project
|
||||||
if not args.notfile:
|
branch = None
|
||||||
project, branch = get_project_info(configs=configs, args=args)
|
if args.entity_type == 'file':
|
||||||
|
project, branch = get_project_info(configs, args)
|
||||||
|
|
||||||
kwargs = vars(args)
|
kwargs = vars(args)
|
||||||
kwargs['project'] = project
|
kwargs['project'] = project
|
||||||
|
@ -418,7 +433,7 @@ def main(argv):
|
||||||
break
|
break
|
||||||
sent = send_heartbeat(
|
sent = send_heartbeat(
|
||||||
project=heartbeat['project'],
|
project=heartbeat['project'],
|
||||||
targetFile=heartbeat['file'],
|
entity=heartbeat['entity'],
|
||||||
timestamp=heartbeat['time'],
|
timestamp=heartbeat['time'],
|
||||||
branch=heartbeat['branch'],
|
branch=heartbeat['branch'],
|
||||||
hostname=kwargs['hostname'],
|
hostname=kwargs['hostname'],
|
||||||
|
@ -428,7 +443,7 @@ def main(argv):
|
||||||
plugin=heartbeat['plugin'],
|
plugin=heartbeat['plugin'],
|
||||||
offline=args.offline,
|
offline=args.offline,
|
||||||
hidefilenames=args.hidefilenames,
|
hidefilenames=args.hidefilenames,
|
||||||
notfile=args.notfile,
|
entity_type=heartbeat['type'],
|
||||||
proxy=args.proxy,
|
proxy=args.proxy,
|
||||||
api_url=args.api_url,
|
api_url=args.api_url,
|
||||||
)
|
)
|
|
@ -28,13 +28,15 @@ log = logging.getLogger('WakaTime')
|
||||||
|
|
||||||
|
|
||||||
class Queue(object):
|
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):
|
def connect(self):
|
||||||
conn = sqlite3.connect(self.DB_FILE)
|
conn = sqlite3.connect(self.db_file)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
c.execute('''CREATE TABLE IF NOT EXISTS heartbeat (
|
c.execute('''CREATE TABLE IF NOT EXISTS {0} (
|
||||||
file text,
|
entity text,
|
||||||
|
type text,
|
||||||
time real,
|
time real,
|
||||||
project text,
|
project text,
|
||||||
branch text,
|
branch text,
|
||||||
|
@ -42,7 +44,7 @@ class Queue(object):
|
||||||
stats text,
|
stats text,
|
||||||
misc text,
|
misc text,
|
||||||
plugin text)
|
plugin text)
|
||||||
''')
|
'''.format(self.table_name))
|
||||||
return (conn, c)
|
return (conn, c)
|
||||||
|
|
||||||
|
|
||||||
|
@ -52,7 +54,8 @@ class Queue(object):
|
||||||
try:
|
try:
|
||||||
conn, c = self.connect()
|
conn, c = self.connect()
|
||||||
heartbeat = {
|
heartbeat = {
|
||||||
'file': u(data.get('entity')),
|
'entity': u(data.get('entity')),
|
||||||
|
'type': u(data.get('type')),
|
||||||
'time': data.get('time'),
|
'time': data.get('time'),
|
||||||
'project': u(data.get('project')),
|
'project': u(data.get('project')),
|
||||||
'branch': u(data.get('branch')),
|
'branch': u(data.get('branch')),
|
||||||
|
@ -61,7 +64,7 @@ class Queue(object):
|
||||||
'misc': u(misc),
|
'misc': u(misc),
|
||||||
'plugin': u(plugin),
|
'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.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
except sqlite3.Error:
|
except sqlite3.Error:
|
||||||
|
@ -83,13 +86,13 @@ class Queue(object):
|
||||||
while loop and tries > -1:
|
while loop and tries > -1:
|
||||||
try:
|
try:
|
||||||
c.execute('BEGIN IMMEDIATE')
|
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()
|
row = c.fetchone()
|
||||||
if row is not None:
|
if row is not None:
|
||||||
values = []
|
values = []
|
||||||
clauses = []
|
clauses = []
|
||||||
index = 0
|
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:
|
if row[index] is not None:
|
||||||
clauses.append('{0}=?'.format(row_name))
|
clauses.append('{0}=?'.format(row_name))
|
||||||
values.append(row[index])
|
values.append(row[index])
|
||||||
|
@ -97,20 +100,21 @@ class Queue(object):
|
||||||
clauses.append('{0} IS NULL'.format(row_name))
|
clauses.append('{0} IS NULL'.format(row_name))
|
||||||
index += 1
|
index += 1
|
||||||
if len(values) > 0:
|
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:
|
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()
|
conn.commit()
|
||||||
if row is not None:
|
if row is not None:
|
||||||
heartbeat = {
|
heartbeat = {
|
||||||
'file': row[0],
|
'entity': row[0],
|
||||||
'time': row[1],
|
'type': row[1],
|
||||||
'project': row[2],
|
'time': row[2],
|
||||||
'branch': row[3],
|
'project': row[3],
|
||||||
'is_write': True if row[4] is 1 else False,
|
'branch': row[4],
|
||||||
'stats': row[5],
|
'is_write': True if row[5] is 1 else False,
|
||||||
'misc': row[6],
|
'stats': row[6],
|
||||||
'plugin': row[7],
|
'misc': row[7],
|
||||||
|
'plugin': row[8],
|
||||||
}
|
}
|
||||||
loop = False
|
loop = False
|
||||||
except sqlite3.Error:
|
except sqlite3.Error:
|
||||||
|
|
|
@ -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.
|
"""Find the current project and branch.
|
||||||
|
|
||||||
First looks for a .wakatime-project file. Second, uses the --project arg.
|
First looks for a .wakatime-project file. Second, uses the --project arg.
|
||||||
|
@ -50,9 +50,9 @@ def get_project_info(configs=None, args=None):
|
||||||
plugin_name = plugin_cls.__name__.lower()
|
plugin_name = plugin_cls.__name__.lower()
|
||||||
plugin_configs = get_configs_for_plugin(plugin_name, configs)
|
plugin_configs = get_configs_for_plugin(plugin_name, configs)
|
||||||
|
|
||||||
project = plugin_cls(args.targetFile, configs=plugin_configs)
|
project = plugin_cls(args.entity, configs=plugin_configs)
|
||||||
if project.process():
|
if project.process():
|
||||||
project_name = project.name()
|
project_name = project_name or project.name()
|
||||||
branch_name = project.branch()
|
branch_name = project.branch()
|
||||||
break
|
break
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ def get_project_info(configs=None, args=None):
|
||||||
plugin_name = plugin_cls.__name__.lower()
|
plugin_name = plugin_cls.__name__.lower()
|
||||||
plugin_configs = get_configs_for_plugin(plugin_name, configs)
|
plugin_configs = get_configs_for_plugin(plugin_name, configs)
|
||||||
|
|
||||||
project = plugin_cls(args.targetFile, configs=plugin_configs)
|
project = plugin_cls(args.entity, configs=plugin_configs)
|
||||||
if project.process():
|
if project.process():
|
||||||
project_name = project_name or project.name()
|
project_name = project_name or project.name()
|
||||||
branch_name = branch_name or project.branch()
|
branch_name = branch_name or project.branch()
|
||||||
|
|
|
@ -153,8 +153,8 @@ def number_lines_in_file(file_name):
|
||||||
return lines
|
return lines
|
||||||
|
|
||||||
|
|
||||||
def get_file_stats(file_name, notfile=False, lineno=None, cursorpos=None):
|
def get_file_stats(file_name, entity_type='file', lineno=None, cursorpos=None):
|
||||||
if notfile:
|
if entity_type != 'file':
|
||||||
stats = {
|
stats = {
|
||||||
'language': None,
|
'language': None,
|
||||||
'dependencies': [],
|
'dependencies': [],
|
||||||
|
|
Loading…
Reference in a new issue