mirror of
https://github.com/wakatime/sublime-wakatime.git
synced 2023-08-10 21:13:02 +03:00
Compare commits
10 Commits
Author | SHA1 | Date | |
---|---|---|---|
ac2ec0e73c | |||
040a76b93c | |||
dab0621b97 | |||
675f9ecd69 | |||
a6f92b9c74 | |||
bfcc242d7e | |||
762027644f | |||
3c4ceb95fa | |||
d6d8bceca0 | |||
acaad2dc83 |
20
HISTORY.rst
20
HISTORY.rst
@ -3,6 +3,26 @@ History
|
||||
-------
|
||||
|
||||
|
||||
4.0.4 (2015-05-12)
|
||||
++++++++++++++++++
|
||||
|
||||
- reuse SSL connection over multiple processes for improved performance
|
||||
- upgrade wakatime cli to v4.0.11
|
||||
|
||||
|
||||
4.0.3 (2015-05-06)
|
||||
++++++++++++++++++
|
||||
|
||||
- send cursorpos to wakatime cli
|
||||
- upgrade wakatime cli to v4.0.10
|
||||
|
||||
|
||||
4.0.2 (2015-05-06)
|
||||
++++++++++++++++++
|
||||
|
||||
- only send heartbeats for the currently active buffer
|
||||
|
||||
|
||||
4.0.1 (2015-05-06)
|
||||
++++++++++++++++++
|
||||
|
||||
|
21
WakaTime.py
21
WakaTime.py
@ -7,7 +7,7 @@ Website: https://wakatime.com/
|
||||
==========================================================="""
|
||||
|
||||
|
||||
__version__ = '4.0.1'
|
||||
__version__ = '4.0.4'
|
||||
|
||||
|
||||
import sublime
|
||||
@ -173,6 +173,16 @@ def find_project_from_folders(folders, current_file):
|
||||
return os.path.basename(folder) if folder else None
|
||||
|
||||
|
||||
def is_view_active(view):
|
||||
if view:
|
||||
active_window = sublime.active_window()
|
||||
if active_window:
|
||||
active_view = active_window.active_view()
|
||||
if active_view:
|
||||
return active_view.buffer_id() == view.buffer_id()
|
||||
return False
|
||||
|
||||
|
||||
def handle_heartbeat(view, is_write=False):
|
||||
window = view.window()
|
||||
if window is not None:
|
||||
@ -197,6 +207,7 @@ class SendHeartbeatThread(threading.Thread):
|
||||
self.api_key = SETTINGS.get('api_key', '')
|
||||
self.ignore = SETTINGS.get('ignore', [])
|
||||
self.last_heartbeat = LAST_HEARTBEAT.copy()
|
||||
self.cursorpos = view.sel()[0].begin() if view.sel() else None
|
||||
self.view = view
|
||||
|
||||
def run(self):
|
||||
@ -226,6 +237,8 @@ class SendHeartbeatThread(threading.Thread):
|
||||
project_name = find_project_from_folders(self.folders, self.target_file)
|
||||
if project_name:
|
||||
cmd.extend(['--project', project_name])
|
||||
if self.cursorpos is not None:
|
||||
cmd.extend(['--cursorpos', '{0}'.format(self.cursorpos)])
|
||||
for pattern in self.ignore:
|
||||
cmd.extend(['--ignore', pattern])
|
||||
if self.debug:
|
||||
@ -288,10 +301,12 @@ class WakatimeListener(sublime_plugin.EventListener):
|
||||
handle_heartbeat(view, is_write=True)
|
||||
|
||||
def on_selection_modified(self, view):
|
||||
handle_heartbeat(view)
|
||||
if is_view_active(view):
|
||||
handle_heartbeat(view)
|
||||
|
||||
def on_modified(self, view):
|
||||
handle_heartbeat(view)
|
||||
if is_view_active(view):
|
||||
handle_heartbeat(view)
|
||||
|
||||
|
||||
class WakatimeDashboardCommand(sublime_plugin.ApplicationCommand):
|
||||
|
@ -1,7 +1,7 @@
|
||||
__title__ = 'wakatime'
|
||||
__description__ = 'Common interface to the WakaTime api.'
|
||||
__url__ = 'https://github.com/wakatime/wakatime'
|
||||
__version_info__ = ('4', '0', '8')
|
||||
__version_info__ = ('4', '0', '11')
|
||||
__version__ = '.'.join(__version_info__)
|
||||
__author__ = 'Alan Hamlett'
|
||||
__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 .compat import u, open, is_py3
|
||||
from .offlinequeue import Queue
|
||||
from .logger import setup_logging
|
||||
from .project import find_project
|
||||
from .stats import get_file_stats
|
||||
from .offlinequeue import Queue
|
||||
from .packages import argparse
|
||||
from .packages import simplejson as json
|
||||
from .packages import requests
|
||||
from .packages.requests.exceptions import RequestException
|
||||
from .project import find_project
|
||||
from .session_cache import SessionCache
|
||||
from .stats import get_file_stats
|
||||
try:
|
||||
from .packages import tzlocal
|
||||
except:
|
||||
@ -147,6 +147,10 @@ def parseArguments(argv):
|
||||
type=float,
|
||||
help='optional floating-point unix epoch timestamp; '+
|
||||
'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',
|
||||
help='when set, will accept any value for the file. for example, '+
|
||||
'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']
|
||||
if stats.get('dependencies'):
|
||||
data['dependencies'] = stats['dependencies']
|
||||
if stats.get('lineno'):
|
||||
data['lineno'] = stats['lineno']
|
||||
if stats.get('cursorpos'):
|
||||
data['cursorpos'] = stats['cursorpos']
|
||||
if isWrite:
|
||||
data['is_write'] = isWrite
|
||||
if project:
|
||||
@ -352,10 +360,13 @@ def send_heartbeat(project=None, branch=None, stats={}, key=None, targetFile=Non
|
||||
if tz:
|
||||
headers['TimeZone'] = u(tz.zone)
|
||||
|
||||
session_cache = SessionCache()
|
||||
session = session_cache.get()
|
||||
|
||||
# log time to api
|
||||
response = None
|
||||
try:
|
||||
response = requests.post(api_url, data=request_body, headers=headers,
|
||||
response = session.post(api_url, data=request_body, headers=headers,
|
||||
proxies=proxies)
|
||||
except RequestException:
|
||||
exception_data = {
|
||||
@ -377,6 +388,7 @@ def send_heartbeat(project=None, branch=None, stats={}, key=None, targetFile=Non
|
||||
log.debug({
|
||||
'response_code': response_code,
|
||||
})
|
||||
session_cache.save(session)
|
||||
return True
|
||||
if offline:
|
||||
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_content': response_content,
|
||||
})
|
||||
session_cache.delete()
|
||||
return False
|
||||
|
||||
|
||||
@ -424,7 +437,8 @@ def main(argv=None):
|
||||
|
||||
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
|
||||
if not args.notfile:
|
||||
|
@ -1,10 +1,9 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
wakatime.queue
|
||||
~~~~~~~~~~~~~~
|
||||
wakatime.offlinequeue
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Queue for offline time logging.
|
||||
http://wakatime.com
|
||||
Queue for saving heartbeats while offline.
|
||||
|
||||
:copyright: (c) 2014 Alan Hamlett.
|
||||
:license: BSD, see LICENSE for more details.
|
||||
|
109
packages/wakatime/session_cache.py
Normal file
109
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
|
||||
|
||||
|
||||
def get_file_stats(file_name, notfile=False):
|
||||
def get_file_stats(file_name, notfile=False, lineno=None, cursorpos=None):
|
||||
if notfile:
|
||||
stats = {
|
||||
'language': None,
|
||||
'dependencies': [],
|
||||
'lines': None,
|
||||
'lineno': lineno,
|
||||
'cursorpos': cursorpos,
|
||||
}
|
||||
else:
|
||||
language, lexer = guess_language(file_name)
|
||||
@ -101,5 +103,7 @@ def get_file_stats(file_name, notfile=False):
|
||||
'language': language,
|
||||
'dependencies': dependencies,
|
||||
'lines': number_lines_in_file(file_name),
|
||||
'lineno': lineno,
|
||||
'cursorpos': cursorpos,
|
||||
}
|
||||
return stats
|
||||
|
Reference in New Issue
Block a user