upgrade wakatime cli to v4.0.11
This commit is contained in:
parent
12cbeb1ce3
commit
81f2c1fbeb
6 changed files with 151 additions and 19 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', '0', '8')
|
__version_info__ = ('4', '0', '11')
|
||||||
__version__ = '.'.join(__version_info__)
|
__version__ = '.'.join(__version_info__)
|
||||||
__author__ = 'Alan Hamlett'
|
__author__ = 'Alan Hamlett'
|
||||||
__author_email__ = 'alan@wakatime.com'
|
__author_email__ = 'alan@wakatime.com'
|
||||||
|
|
|
@ -29,14 +29,14 @@ 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 .offlinequeue import Queue
|
|
||||||
from .logger import setup_logging
|
from .logger import setup_logging
|
||||||
from .project import find_project
|
from .offlinequeue import Queue
|
||||||
from .stats import get_file_stats
|
|
||||||
from .packages import argparse
|
from .packages import argparse
|
||||||
from .packages import simplejson as json
|
from .packages import simplejson as json
|
||||||
from .packages import requests
|
|
||||||
from .packages.requests.exceptions import RequestException
|
from .packages.requests.exceptions import RequestException
|
||||||
|
from .project import find_project
|
||||||
|
from .session_cache import SessionCache
|
||||||
|
from .stats import get_file_stats
|
||||||
try:
|
try:
|
||||||
from .packages import tzlocal
|
from .packages import tzlocal
|
||||||
except:
|
except:
|
||||||
|
@ -147,6 +147,10 @@ def parseArguments(argv):
|
||||||
type=float,
|
type=float,
|
||||||
help='optional floating-point unix epoch timestamp; '+
|
help='optional floating-point unix epoch timestamp; '+
|
||||||
'uses current time by default')
|
'uses current time by default')
|
||||||
|
parser.add_argument('--lineno', dest='lineno',
|
||||||
|
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',
|
parser.add_argument('--notfile', dest='notfile', action='store_true',
|
||||||
help='when set, will accept any value for the file. for example, '+
|
help='when set, will accept any value for the file. for example, '+
|
||||||
'a domain name or other item you want to log time towards.')
|
'a domain name or other item you want to log time towards.')
|
||||||
|
@ -322,6 +326,10 @@ def send_heartbeat(project=None, branch=None, stats={}, key=None, targetFile=Non
|
||||||
data['language'] = stats['language']
|
data['language'] = stats['language']
|
||||||
if stats.get('dependencies'):
|
if stats.get('dependencies'):
|
||||||
data['dependencies'] = stats['dependencies']
|
data['dependencies'] = stats['dependencies']
|
||||||
|
if stats.get('lineno'):
|
||||||
|
data['lineno'] = stats['lineno']
|
||||||
|
if stats.get('cursorpos'):
|
||||||
|
data['cursorpos'] = stats['cursorpos']
|
||||||
if isWrite:
|
if isWrite:
|
||||||
data['is_write'] = isWrite
|
data['is_write'] = isWrite
|
||||||
if project:
|
if project:
|
||||||
|
@ -352,10 +360,13 @@ def send_heartbeat(project=None, branch=None, stats={}, key=None, targetFile=Non
|
||||||
if tz:
|
if tz:
|
||||||
headers['TimeZone'] = u(tz.zone)
|
headers['TimeZone'] = u(tz.zone)
|
||||||
|
|
||||||
|
session_cache = SessionCache()
|
||||||
|
session = session_cache.get()
|
||||||
|
|
||||||
# log time to api
|
# log time to api
|
||||||
response = None
|
response = None
|
||||||
try:
|
try:
|
||||||
response = requests.post(api_url, data=request_body, headers=headers,
|
response = session.post(api_url, data=request_body, headers=headers,
|
||||||
proxies=proxies)
|
proxies=proxies)
|
||||||
except RequestException:
|
except RequestException:
|
||||||
exception_data = {
|
exception_data = {
|
||||||
|
@ -377,6 +388,7 @@ def send_heartbeat(project=None, branch=None, stats={}, key=None, targetFile=Non
|
||||||
log.debug({
|
log.debug({
|
||||||
'response_code': response_code,
|
'response_code': response_code,
|
||||||
})
|
})
|
||||||
|
session_cache.save(session)
|
||||||
return True
|
return True
|
||||||
if offline:
|
if offline:
|
||||||
if response_code != 400:
|
if response_code != 400:
|
||||||
|
@ -402,6 +414,7 @@ def send_heartbeat(project=None, branch=None, stats={}, key=None, targetFile=Non
|
||||||
'response_code': response_code,
|
'response_code': response_code,
|
||||||
'response_content': response_content,
|
'response_content': response_content,
|
||||||
})
|
})
|
||||||
|
session_cache.delete()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
@ -424,7 +437,8 @@ def main(argv=None):
|
||||||
|
|
||||||
if os.path.isfile(args.targetFile) or args.notfile:
|
if os.path.isfile(args.targetFile) or args.notfile:
|
||||||
|
|
||||||
stats = get_file_stats(args.targetFile, notfile=args.notfile)
|
stats = get_file_stats(args.targetFile, notfile=args.notfile,
|
||||||
|
lineno=args.lineno, cursorpos=args.cursorpos)
|
||||||
|
|
||||||
project = None
|
project = None
|
||||||
if not args.notfile:
|
if not args.notfile:
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
:license: BSD, see LICENSE for more details.
|
:license: BSD, see LICENSE for more details.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import inspect
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
@ -47,14 +48,19 @@ class JsonFormatter(logging.Formatter):
|
||||||
def format(self, record):
|
def format(self, record):
|
||||||
data = OrderedDict([
|
data = OrderedDict([
|
||||||
('now', self.formatTime(record, self.datefmt)),
|
('now', self.formatTime(record, self.datefmt)),
|
||||||
('version', self.version),
|
|
||||||
('plugin', self.plugin),
|
|
||||||
('time', self.timestamp),
|
|
||||||
('isWrite', self.isWrite),
|
|
||||||
('file', self.targetFile),
|
|
||||||
('level', record.levelname),
|
|
||||||
('message', record.msg),
|
|
||||||
])
|
])
|
||||||
|
try:
|
||||||
|
data['package'] = inspect.stack()[9][0].f_globals.get('__package__')
|
||||||
|
data['lineno'] = inspect.stack()[9][2]
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
data['version'] = self.version
|
||||||
|
data['plugin'] = self.plugin
|
||||||
|
data['time'] = self.timestamp
|
||||||
|
data['isWrite'] = self.isWrite
|
||||||
|
data['file'] = self.targetFile
|
||||||
|
data['level'] = record.levelname
|
||||||
|
data['message'] = record.msg
|
||||||
if not self.plugin:
|
if not self.plugin:
|
||||||
del data['plugin']
|
del data['plugin']
|
||||||
if not self.isWrite:
|
if not self.isWrite:
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""
|
"""
|
||||||
wakatime.queue
|
wakatime.offlinequeue
|
||||||
~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Queue for offline time logging.
|
Queue for saving heartbeats while offline.
|
||||||
http://wakatime.com
|
|
||||||
|
|
||||||
:copyright: (c) 2014 Alan Hamlett.
|
:copyright: (c) 2014 Alan Hamlett.
|
||||||
:license: BSD, see LICENSE for more details.
|
:license: BSD, see LICENSE for more details.
|
||||||
|
|
109
plugin/packages/wakatime/session_cache.py
Normal file
109
plugin/packages/wakatime/session_cache.py
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
wakatime.session_cache
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Persist requests.Session for multiprocess SSL handshake pooling.
|
||||||
|
|
||||||
|
:copyright: (c) 2015 Alan Hamlett.
|
||||||
|
:license: BSD, see LICENSE for more details.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import pickle
|
||||||
|
import sys
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
try:
|
||||||
|
import sqlite3
|
||||||
|
HAS_SQL = True
|
||||||
|
except ImportError:
|
||||||
|
HAS_SQL = False
|
||||||
|
|
||||||
|
sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), 'packages'))
|
||||||
|
|
||||||
|
from .packages import requests
|
||||||
|
|
||||||
|
|
||||||
|
log = logging.getLogger('WakaTime')
|
||||||
|
|
||||||
|
|
||||||
|
class SessionCache(object):
|
||||||
|
DB_FILE = os.path.join(os.path.expanduser('~'), '.wakatime.db')
|
||||||
|
|
||||||
|
def connect(self):
|
||||||
|
conn = sqlite3.connect(self.DB_FILE)
|
||||||
|
c = conn.cursor()
|
||||||
|
c.execute('''CREATE TABLE IF NOT EXISTS session (
|
||||||
|
value BLOB)
|
||||||
|
''')
|
||||||
|
return (conn, c)
|
||||||
|
|
||||||
|
|
||||||
|
def save(self, session):
|
||||||
|
"""Saves a requests.Session object for the next heartbeat process.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if not HAS_SQL:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
conn, c = self.connect()
|
||||||
|
c.execute('DELETE FROM session')
|
||||||
|
values = {
|
||||||
|
'value': pickle.dumps(session),
|
||||||
|
}
|
||||||
|
c.execute('INSERT INTO session VALUES (:value)', values)
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
except:
|
||||||
|
log.error(traceback.format_exc())
|
||||||
|
|
||||||
|
|
||||||
|
def get(self):
|
||||||
|
"""Returns a requests.Session object.
|
||||||
|
|
||||||
|
Gets Session from sqlite3 cache or creates a new Session.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if not HAS_SQL:
|
||||||
|
return requests.session()
|
||||||
|
|
||||||
|
try:
|
||||||
|
conn, c = self.connect()
|
||||||
|
except:
|
||||||
|
log.error(traceback.format_exc())
|
||||||
|
return requests.session()
|
||||||
|
|
||||||
|
session = None
|
||||||
|
try:
|
||||||
|
c.execute('BEGIN IMMEDIATE')
|
||||||
|
c.execute('SELECT value FROM session LIMIT 1')
|
||||||
|
row = c.fetchone()
|
||||||
|
if row is not None:
|
||||||
|
session = pickle.loads(row[0])
|
||||||
|
except:
|
||||||
|
log.error(traceback.format_exc())
|
||||||
|
|
||||||
|
try:
|
||||||
|
conn.close()
|
||||||
|
except:
|
||||||
|
log.error(traceback.format_exc())
|
||||||
|
|
||||||
|
return session if session is not None else requests.session()
|
||||||
|
|
||||||
|
|
||||||
|
def delete(self):
|
||||||
|
"""Clears all cached Session objects.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if not HAS_SQL:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
conn, c = self.connect()
|
||||||
|
c.execute('DELETE FROM session')
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
except:
|
||||||
|
log.error(traceback.format_exc())
|
|
@ -86,12 +86,14 @@ def number_lines_in_file(file_name):
|
||||||
return lines
|
return lines
|
||||||
|
|
||||||
|
|
||||||
def get_file_stats(file_name, notfile=False):
|
def get_file_stats(file_name, notfile=False, lineno=None, cursorpos=None):
|
||||||
if notfile:
|
if notfile:
|
||||||
stats = {
|
stats = {
|
||||||
'language': None,
|
'language': None,
|
||||||
'dependencies': [],
|
'dependencies': [],
|
||||||
'lines': None,
|
'lines': None,
|
||||||
|
'lineno': lineno,
|
||||||
|
'cursorpos': cursorpos,
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
language, lexer = guess_language(file_name)
|
language, lexer = guess_language(file_name)
|
||||||
|
@ -101,5 +103,7 @@ def get_file_stats(file_name, notfile=False):
|
||||||
'language': language,
|
'language': language,
|
||||||
'dependencies': dependencies,
|
'dependencies': dependencies,
|
||||||
'lines': number_lines_in_file(file_name),
|
'lines': number_lines_in_file(file_name),
|
||||||
|
'lineno': lineno,
|
||||||
|
'cursorpos': cursorpos,
|
||||||
}
|
}
|
||||||
return stats
|
return stats
|
||||||
|
|
Loading…
Reference in a new issue