support for offline time logging
This commit is contained in:
parent
5eb2ad4bea
commit
22766bb14b
2 changed files with 137 additions and 8 deletions
|
@ -39,6 +39,7 @@ except ImportError:
|
|||
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), 'packages'))
|
||||
from .queue import Queue
|
||||
from .log import setup_logging
|
||||
from .project import find_project
|
||||
from .stats import get_file_stats
|
||||
|
@ -153,6 +154,9 @@ def parseArguments(argv):
|
|||
parser.add_argument('--key', dest='key',
|
||||
help='your wakatime api key; uses api_key from '+
|
||||
'~/.wakatime.conf by default')
|
||||
parser.add_argument('--disableoffline', dest='offline',
|
||||
action='store_false',
|
||||
help='disables offline time logging instead of queuing logged time')
|
||||
parser.add_argument('--ignore', dest='ignore', action='append',
|
||||
help='filename patterns to ignore; POSIX regex syntax; can be used more than once')
|
||||
parser.add_argument('--logfile', dest='logfile',
|
||||
|
@ -193,6 +197,8 @@ def parseArguments(argv):
|
|||
args.ignore.append(pattern)
|
||||
except TypeError:
|
||||
pass
|
||||
if args.offline and configs.has_option('settings', 'offline'):
|
||||
args.offline = configs.getboolean('settings', 'offline')
|
||||
if not args.verbose and configs.has_option('settings', 'verbose'):
|
||||
args.verbose = configs.getboolean('settings', 'verbose')
|
||||
if not args.verbose and configs.has_option('settings', 'debug'):
|
||||
|
@ -227,8 +233,8 @@ def get_user_agent(plugin):
|
|||
return user_agent
|
||||
|
||||
|
||||
def send_action(project=None, branch=None, stats={}, key=None, targetFile=None,
|
||||
timestamp=None, isWrite=None, plugin=None, **kwargs):
|
||||
def send_action(project=None, branch=None, stats=None, key=None, targetFile=None,
|
||||
timestamp=None, isWrite=None, plugin=None, offline=None, **kwargs):
|
||||
url = 'https://wakatime.com/api/v1/actions'
|
||||
log.debug('Sending action to api at %s' % url)
|
||||
data = {
|
||||
|
@ -270,6 +276,12 @@ def send_action(project=None, branch=None, stats={}, key=None, targetFile=None,
|
|||
}
|
||||
if log.isEnabledFor(logging.DEBUG):
|
||||
exception_data['traceback'] = traceback.format_exc()
|
||||
if offline:
|
||||
queue = Queue()
|
||||
queue.push(data, plugin)
|
||||
if log.isEnabledFor(logging.DEBUG):
|
||||
log.warn(exception_data)
|
||||
else:
|
||||
log.error(exception_data)
|
||||
except:
|
||||
exception_data = {
|
||||
|
@ -277,6 +289,12 @@ def send_action(project=None, branch=None, stats={}, key=None, targetFile=None,
|
|||
}
|
||||
if log.isEnabledFor(logging.DEBUG):
|
||||
exception_data['traceback'] = traceback.format_exc()
|
||||
if offline:
|
||||
queue = Queue()
|
||||
queue.push(data, plugin)
|
||||
if log.isEnabledFor(logging.DEBUG):
|
||||
log.warn(exception_data)
|
||||
else:
|
||||
log.error(exception_data)
|
||||
else:
|
||||
if response.getcode() == 201:
|
||||
|
@ -284,6 +302,15 @@ def send_action(project=None, branch=None, stats={}, key=None, targetFile=None,
|
|||
'response_code': response.getcode(),
|
||||
})
|
||||
return True
|
||||
if offline:
|
||||
queue = Queue()
|
||||
queue.push(data, plugin)
|
||||
if log.isEnabledFor(logging.DEBUG):
|
||||
log.warn({
|
||||
'response_code': response.getcode(),
|
||||
'response_content': response.read(),
|
||||
})
|
||||
else:
|
||||
log.error({
|
||||
'response_code': response.getcode(),
|
||||
'response_content': response.read(),
|
||||
|
@ -323,6 +350,15 @@ def main(argv=None):
|
|||
stats=stats,
|
||||
**vars(args)
|
||||
):
|
||||
queue = Queue()
|
||||
while True:
|
||||
action = queue.pop()
|
||||
if action is None:
|
||||
break
|
||||
if not send_action(project=action['project'], targetFile=action['file'], timestamp=action['time'],
|
||||
branch=action['branch'], stats={'language': action['language'], 'lines': action['lines']},
|
||||
key=args.key, isWrite=action['is_write'], plugin=action['plugin'], offline=args.offline):
|
||||
break
|
||||
return 0 # success
|
||||
|
||||
return 102 # api error
|
||||
|
|
93
wakatime/queue.py
Normal file
93
wakatime/queue.py
Normal file
|
@ -0,0 +1,93 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
wakatime.queue
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
Queue for offline time logging.
|
||||
http://wakatime.com
|
||||
|
||||
:copyright: (c) 2014 Alan Hamlett.
|
||||
:license: BSD, see LICENSE for more details.
|
||||
"""
|
||||
|
||||
|
||||
import logging
|
||||
import os
|
||||
import sqlite3
|
||||
from time import sleep
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Queue(object):
|
||||
DB_FILE = os.path.join(os.path.expanduser('~'), '.wakatime.db')
|
||||
|
||||
def connect(self):
|
||||
exists = os.path.exists(self.DB_FILE)
|
||||
conn = sqlite3.connect(self.DB_FILE)
|
||||
c = conn.cursor()
|
||||
c.execute('''CREATE TABLE IF NOT EXISTS action (
|
||||
file text,
|
||||
time real,
|
||||
project text,
|
||||
language text,
|
||||
lines integer,
|
||||
branch text,
|
||||
is_write integer,
|
||||
plugin text)
|
||||
''')
|
||||
return (conn, c)
|
||||
|
||||
|
||||
def push(self, data, plugin):
|
||||
conn, c = self.connect()
|
||||
action = {
|
||||
'file': data.get('file'),
|
||||
'time': data.get('time'),
|
||||
'project': data.get('project'),
|
||||
'language': data.get('language'),
|
||||
'lines': data.get('lines'),
|
||||
'branch': data.get('branch'),
|
||||
'is_write': 1 if data.get('is_write') else 0,
|
||||
'plugin': plugin,
|
||||
}
|
||||
c.execute('INSERT INTO action VALUES (:file,:time,:project,:language,:lines,:branch,:is_write,:plugin)', action)
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
|
||||
def pop(self):
|
||||
tries = 3
|
||||
wait = 0.1
|
||||
action = None
|
||||
conn, c = self.connect()
|
||||
loop = True
|
||||
while loop and tries > -1:
|
||||
try:
|
||||
c.execute('BEGIN IMMEDIATE')
|
||||
c.execute('SELECT * FROM action LIMIT 1')
|
||||
row = c.fetchone()
|
||||
if row is not None:
|
||||
c.execute('''DELETE FROM action WHERE
|
||||
file=? AND time=? AND project=? AND language=? AND
|
||||
lines=? AND branch=? AND is_write=?''', row[0:7])
|
||||
conn.commit()
|
||||
if row is not None:
|
||||
action = {
|
||||
'file': row[0],
|
||||
'time': row[1],
|
||||
'project': row[2],
|
||||
'language': row[3],
|
||||
'lines': row[4],
|
||||
'branch': row[5],
|
||||
'is_write': True if row[6] is 1 else False,
|
||||
'plugin': row[7],
|
||||
}
|
||||
loop = False
|
||||
except sqlite3.Error, e:
|
||||
log.debug(str(e))
|
||||
sleep(wait)
|
||||
tries -= 1
|
||||
conn.close()
|
||||
return action
|
Loading…
Reference in a new issue