upgrade wakatime cli to v4.0.4
This commit is contained in:
parent
307029c37a
commit
440e33b8b7
1087 changed files with 21913 additions and 587 deletions
26
WakaTime.py
26
WakaTime.py
|
@ -24,7 +24,7 @@ from os.path import expanduser, dirname, basename, realpath, join
|
|||
ACTION_FREQUENCY = 2
|
||||
ST_VERSION = int(sublime.version())
|
||||
PLUGIN_DIR = dirname(realpath(__file__))
|
||||
API_CLIENT = '%s/packages/wakatime/wakatime-cli.py' % PLUGIN_DIR
|
||||
API_CLIENT = '%s/packages/wakatime/cli.py' % PLUGIN_DIR
|
||||
SETTINGS_FILE = 'WakaTime.sublime-settings'
|
||||
SETTINGS = {}
|
||||
LAST_ACTION = {
|
||||
|
@ -37,9 +37,7 @@ LOCK = threading.RLock()
|
|||
PYTHON_LOCATION = None
|
||||
|
||||
# add wakatime package to path
|
||||
sys.path.insert(0, join(PLUGIN_DIR, 'packages', 'wakatime'))
|
||||
|
||||
from wakatime import parseConfigFile
|
||||
sys.path.insert(0, join(PLUGIN_DIR, 'packages'))
|
||||
|
||||
# check if we have SSL support
|
||||
try:
|
||||
|
@ -80,10 +78,14 @@ def prompt_api_key():
|
|||
createConfigFile()
|
||||
|
||||
default_key = ''
|
||||
configs = parseConfigFile()
|
||||
if configs is not None:
|
||||
if configs.has_option('settings', 'api_key'):
|
||||
default_key = configs.get('settings', 'api_key')
|
||||
try:
|
||||
from wakatime.base import parseConfigFile
|
||||
configs = parseConfigFile()
|
||||
if configs is not None:
|
||||
if configs.has_option('settings', 'api_key'):
|
||||
default_key = configs.get('settings', 'api_key')
|
||||
except:
|
||||
pass
|
||||
|
||||
if SETTINGS.get('api_key'):
|
||||
return True
|
||||
|
@ -208,8 +210,8 @@ class SendActionThread(threading.Thread):
|
|||
if self.debug:
|
||||
cmd.append('--verbose')
|
||||
if HAS_SSL:
|
||||
if self.debug:
|
||||
print('[WakaTime] %s' % ' '.join(cmd))
|
||||
#if self.debug:
|
||||
print('[WakaTime] %s' % ' '.join(cmd))
|
||||
code = wakatime.main(cmd)
|
||||
if code != 0:
|
||||
print('[WakaTime] Error: Response code %d from wakatime package.' % code)
|
||||
|
@ -217,8 +219,8 @@ class SendActionThread(threading.Thread):
|
|||
python = python_binary()
|
||||
if python:
|
||||
cmd.insert(0, python)
|
||||
if self.debug:
|
||||
print('[WakaTime] %s' % ' '.join(cmd))
|
||||
#if self.debug:
|
||||
print('[WakaTime] %s %s' % (python, ' '.join(cmd)))
|
||||
if platform.system() == 'Windows':
|
||||
Popen(cmd, shell=False)
|
||||
else:
|
||||
|
|
39
packages/wakatime/.gitignore
vendored
39
packages/wakatime/.gitignore
vendored
|
@ -1,39 +0,0 @@
|
|||
*.py[cod]
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Packages
|
||||
*.egg
|
||||
*.egg-info
|
||||
dist
|
||||
build
|
||||
eggs
|
||||
parts
|
||||
bin
|
||||
var
|
||||
sdist
|
||||
develop-eggs
|
||||
.installed.cfg
|
||||
lib
|
||||
lib64
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
.coverage
|
||||
.tox
|
||||
nosetests.xml
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
|
||||
# Mr Developer
|
||||
.mr.developer.cfg
|
||||
.project
|
||||
.pydevproject
|
||||
|
||||
virtualenv
|
||||
venv
|
||||
.DS_Store
|
|
@ -1,15 +0,0 @@
|
|||
WakaTime is written and maintained by Alan Hamlett and
|
||||
various contributors:
|
||||
|
||||
|
||||
Development Lead
|
||||
----------------
|
||||
|
||||
- Alan Hamlett <alan.hamlett@gmail.com>
|
||||
|
||||
|
||||
Patches and Suggestions
|
||||
-----------------------
|
||||
|
||||
- 3onyc <3onyc@x3tech.com>
|
||||
- userid <xixico@ymail.com>
|
|
@ -1,304 +0,0 @@
|
|||
|
||||
History
|
||||
-------
|
||||
|
||||
|
||||
3.0.5 (2015-01-13)
|
||||
++++++++++++++++++
|
||||
|
||||
- ignore errors from malformed markup (too many closing tags)
|
||||
|
||||
|
||||
3.0.4 (2015-01-06)
|
||||
++++++++++++++++++
|
||||
|
||||
- remove unused dependency, which is missing in some python environments
|
||||
|
||||
|
||||
3.0.3 (2014-12-25)
|
||||
++++++++++++++++++
|
||||
|
||||
- detect JavaScript frameworks from script tags in Html template files
|
||||
|
||||
|
||||
3.0.2 (2014-12-25)
|
||||
++++++++++++++++++
|
||||
|
||||
- detect frameworks from JavaScript and JSON files
|
||||
|
||||
|
||||
3.0.1 (2014-12-23)
|
||||
++++++++++++++++++
|
||||
|
||||
- handle unknown language when parsing dependencies
|
||||
|
||||
|
||||
3.0.0 (2014-12-23)
|
||||
++++++++++++++++++
|
||||
|
||||
- detect libraries and frameworks for C++, Java, .NET, PHP, and Python files
|
||||
|
||||
|
||||
2.1.11 (2014-12-22)
|
||||
+++++++++++++++++++
|
||||
|
||||
- fix offline logging when response from api is None
|
||||
|
||||
|
||||
2.1.10 (2014-12-15)
|
||||
+++++++++++++++++++
|
||||
|
||||
- prevent queuing offline heartbeats which will never be valid (400 errors)
|
||||
|
||||
|
||||
2.1.9 (2014-12-05)
|
||||
++++++++++++++++++
|
||||
|
||||
- fix bug preventing offline heartbeats from being purged after uploaded
|
||||
|
||||
|
||||
2.1.8 (2014-12-04)
|
||||
++++++++++++++++++
|
||||
|
||||
- fix UnicodeDecodeError when building user agent string
|
||||
- handle case where response is None
|
||||
|
||||
|
||||
2.1.7 (2014-11-30)
|
||||
++++++++++++++++++
|
||||
|
||||
- upgrade pygments to v2.0.1
|
||||
- always log an error when api key is incorrect
|
||||
|
||||
|
||||
2.1.6 (2014-11-18)
|
||||
++++++++++++++++++
|
||||
|
||||
- fix list index error when detecting subversion project
|
||||
|
||||
|
||||
2.1.5 (2014-11-17)
|
||||
++++++++++++++++++
|
||||
|
||||
- catch exceptions when getting current machine time zone
|
||||
|
||||
|
||||
2.1.4 (2014-11-12)
|
||||
++++++++++++++++++
|
||||
|
||||
- when Python was not compiled with https support, log an error to the log file
|
||||
|
||||
|
||||
2.1.3 (2014-11-10)
|
||||
++++++++++++++++++
|
||||
|
||||
- correctly detect branch name for subversion projects
|
||||
|
||||
|
||||
2.1.2 (2014-10-07)
|
||||
++++++++++++++++++
|
||||
|
||||
- still log heartbeat when something goes wrong while reading num lines in file
|
||||
|
||||
|
||||
2.1.1 (2014-09-30)
|
||||
++++++++++++++++++
|
||||
|
||||
- fix bug where binary file opened as utf-8
|
||||
|
||||
|
||||
2.1.0 (2014-09-30)
|
||||
++++++++++++++++++
|
||||
|
||||
- python3 compatibility changes
|
||||
|
||||
|
||||
2.0.8 (2014-08-29)
|
||||
++++++++++++++++++
|
||||
|
||||
- supress output from svn command
|
||||
|
||||
|
||||
2.0.7 (2014-08-27)
|
||||
++++++++++++++++++
|
||||
|
||||
- find svn binary location from common install directories
|
||||
|
||||
|
||||
2.0.6 (2014-08-07)
|
||||
++++++++++++++++++
|
||||
|
||||
- encode json data as str when passing to urllib
|
||||
|
||||
|
||||
2.0.5 (2014-07-25)
|
||||
++++++++++++++++++
|
||||
|
||||
- option in .wakatime.cfg to obfuscate file names
|
||||
|
||||
|
||||
2.0.4 (2014-07-25)
|
||||
++++++++++++++++++
|
||||
|
||||
- use unique logger namespace to prevent collisions in shared plugin environments
|
||||
|
||||
|
||||
2.0.3 (2014-06-18)
|
||||
++++++++++++++++++
|
||||
|
||||
- use project from command line arg when no revision control project is found
|
||||
|
||||
|
||||
2.0.2 (2014-06-09)
|
||||
++++++++++++++++++
|
||||
|
||||
- include python3.2 compatible versions of simplejson, pytz, and tzlocal
|
||||
- disable offline logging when Python was not compiled with sqlite3 module
|
||||
|
||||
|
||||
2.0.1 (2014-05-26)
|
||||
++++++++++++++++++
|
||||
|
||||
- fix bug in queue preventing actions with NULL values from being purged
|
||||
|
||||
|
||||
2.0.0 (2014-05-25)
|
||||
++++++++++++++++++
|
||||
|
||||
- offline time logging using sqlite3 to queue editor events
|
||||
|
||||
|
||||
1.0.2 (2014-05-06)
|
||||
++++++++++++++++++
|
||||
|
||||
- ability to set project from command line argument
|
||||
|
||||
|
||||
1.0.1 (2014-03-05)
|
||||
++++++++++++++++++
|
||||
|
||||
- use new domain name wakatime.com
|
||||
|
||||
|
||||
1.0.0 (2014-02-05)
|
||||
++++++++++++++++++
|
||||
|
||||
- detect project name and branch name from mercurial revision control
|
||||
|
||||
|
||||
0.5.3 (2014-01-15)
|
||||
++++++++++++++++++
|
||||
|
||||
- bug fix for unicode in Python3
|
||||
|
||||
|
||||
0.5.2 (2014-01-14)
|
||||
++++++++++++++++++
|
||||
|
||||
- minor bug fix for Subversion on non-English systems
|
||||
|
||||
|
||||
0.5.1 (2013-12-13)
|
||||
++++++++++++++++++
|
||||
|
||||
- second line in .wakatime-project file now sets branch name
|
||||
|
||||
|
||||
0.5.0 (2013-12-13)
|
||||
++++++++++++++++++
|
||||
|
||||
- Convert ~/.wakatime.conf to ~/.wakatime.cfg and use configparser format
|
||||
- new [projectmap] section in cfg file for naming projects based on folders
|
||||
|
||||
|
||||
0.4.10 (2013-11-13)
|
||||
+++++++++++++++++++
|
||||
|
||||
- Placing .wakatime-project file in a folder will read the project's name from that file
|
||||
|
||||
|
||||
0.4.9 (2013-10-27)
|
||||
++++++++++++++++++
|
||||
|
||||
- New config for ignoring files from regular expressions
|
||||
- Parse more options from config file (verbose, logfile, ignore)
|
||||
|
||||
|
||||
0.4.8 (2013-10-13)
|
||||
++++++++++++++++++
|
||||
|
||||
- Read git HEAD file to find current branch instead of running git command line
|
||||
|
||||
|
||||
0.4.7 (2013-09-30)
|
||||
++++++++++++++++++
|
||||
|
||||
- Sending local olson timezone string in api request
|
||||
|
||||
|
||||
0.4.6 (2013-09-22)
|
||||
++++++++++++++++++
|
||||
|
||||
- Sending total lines in file and language name to api
|
||||
|
||||
|
||||
0.4.5 (2013-09-07)
|
||||
++++++++++++++++++
|
||||
|
||||
- Fixed relative import error by adding packages directory to sys path
|
||||
|
||||
|
||||
0.4.4 (2013-09-06)
|
||||
++++++++++++++++++
|
||||
|
||||
- Using urllib2 again because of intermittent problems sending json with requests library
|
||||
|
||||
|
||||
0.4.3 (2013-09-04)
|
||||
++++++++++++++++++
|
||||
|
||||
- Encoding json as utf-8 before making request
|
||||
|
||||
|
||||
0.4.2 (2013-09-04)
|
||||
++++++++++++++++++
|
||||
|
||||
- Using requests package v1.2.3 from pypi
|
||||
|
||||
|
||||
0.4.1 (2013-08-25)
|
||||
++++++++++++++++++
|
||||
|
||||
- Fix bug causing requests library to omit POST content
|
||||
|
||||
|
||||
0.4.0 (2013-08-15)
|
||||
++++++++++++++++++
|
||||
|
||||
- Sending single branch instead of multiple tags
|
||||
|
||||
|
||||
0.3.1 (2013-08-08)
|
||||
++++++++++++++++++
|
||||
|
||||
- Using requests module instead of urllib2 to verify SSL certs
|
||||
|
||||
|
||||
0.3.0 (2013-08-08)
|
||||
++++++++++++++++++
|
||||
|
||||
- Allow importing directly from Python plugins
|
||||
|
||||
|
||||
0.1.1 (2013-07-07)
|
||||
++++++++++++++++++
|
||||
|
||||
- Refactored
|
||||
- Simplified action events schema
|
||||
|
||||
|
||||
0.0.1 (2013-07-05)
|
||||
++++++++++++++++++
|
||||
|
||||
- Birth
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2014 by the respective authors (see AUTHORS file).
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
* Neither the names of WakaTime, nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
|
||||
NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -1,2 +0,0 @@
|
|||
include README.rst LICENSE HISTORY.rst
|
||||
recursive-include wakatime *.py
|
|
@ -1,20 +0,0 @@
|
|||
WakaTime
|
||||
========
|
||||
|
||||
Fully automatic time tracking for programmers.
|
||||
|
||||
This is the common interface for the WakaTime api. You shouldn't need to directly use this package unless you are creating a new plugin or your text editor's plugin asks you to install the wakatime-cli interface.
|
||||
|
||||
Go to http://wakatime.com to install the plugin for your text editor.
|
||||
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
pip install wakatime
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
https://wakatime.com/
|
9
packages/wakatime/__about__.py
Normal file
9
packages/wakatime/__about__.py
Normal file
|
@ -0,0 +1,9 @@
|
|||
__title__ = 'wakatime'
|
||||
__description__ = 'Common interface to the WakaTime api.'
|
||||
__url__ = 'https://github.com/wakatime/wakatime'
|
||||
__version_info__ = ('4', '0', '4')
|
||||
__version__ = '.'.join(__version_info__)
|
||||
__author__ = 'Alan Hamlett'
|
||||
__author_email__ = 'alan@wakatime.com'
|
||||
__license__ = 'BSD'
|
||||
__copyright__ = 'Copyright 2014 Alan Hamlett'
|
17
packages/wakatime/__init__.py
Normal file
17
packages/wakatime/__init__.py
Normal file
|
@ -0,0 +1,17 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
wakatime
|
||||
~~~~~~~~
|
||||
|
||||
Common interface to the WakaTime api.
|
||||
http://wakatime.com
|
||||
|
||||
:copyright: (c) 2013 Alan Hamlett.
|
||||
:license: BSD, see LICENSE for more details.
|
||||
"""
|
||||
|
||||
|
||||
__all__ = ['main']
|
||||
|
||||
|
||||
from .base import main
|
|
@ -1,10 +1,9 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
wakatime
|
||||
~~~~~~~~
|
||||
wakatime.base
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
Common interface to the WakaTime api.
|
||||
http://wakatime.com
|
||||
wakatime module entry point.
|
||||
|
||||
:copyright: (c) 2013 Alan Hamlett.
|
||||
:license: BSD, see LICENSE for more details.
|
||||
|
@ -12,13 +11,6 @@
|
|||
|
||||
from __future__ import print_function
|
||||
|
||||
__title__ = 'wakatime'
|
||||
__version__ = '3.0.5'
|
||||
__author__ = 'Alan Hamlett'
|
||||
__license__ = 'BSD'
|
||||
__copyright__ = 'Copyright 2014 Alan Hamlett'
|
||||
|
||||
|
||||
import base64
|
||||
import logging
|
||||
import os
|
||||
|
@ -31,26 +23,24 @@ try:
|
|||
import ConfigParser as configparser
|
||||
except ImportError:
|
||||
import configparser
|
||||
try:
|
||||
from urllib2 import HTTPError, Request, urlopen
|
||||
except ImportError:
|
||||
from urllib.error import HTTPError
|
||||
from urllib.request import Request, urlopen
|
||||
|
||||
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 .__about__ import __version__
|
||||
from .compat import u, open, is_py3
|
||||
from .queue import Queue
|
||||
from .offlinequeue import Queue
|
||||
from .log import setup_logging
|
||||
from .project import find_project
|
||||
from .stats import get_file_stats
|
||||
from .packages import argparse
|
||||
from .packages import simplejson as json
|
||||
from .packages import requests
|
||||
from .packages.requests.exceptions import RequestException
|
||||
try:
|
||||
from .packages import tzlocal
|
||||
except:
|
||||
from .packages import tzlocal3
|
||||
from .packages import tzlocal3 as tzlocal
|
||||
|
||||
|
||||
log = logging.getLogger('WakaTime')
|
||||
|
@ -143,29 +133,43 @@ def parseArguments(argv):
|
|||
parser.add_argument('--file', dest='targetFile', metavar='file',
|
||||
action=FileAction, required=True,
|
||||
help='absolute path to file for current heartbeat')
|
||||
parser.add_argument('--time', dest='timestamp', metavar='time',
|
||||
type=float,
|
||||
help='optional floating-point unix epoch timestamp; '+
|
||||
'uses current time by default')
|
||||
parser.add_argument('--write', dest='isWrite',
|
||||
action='store_true',
|
||||
help='note heartbeat was triggered from writing to a file')
|
||||
parser.add_argument('--plugin', dest='plugin',
|
||||
help='optional text editor plugin name and version '+
|
||||
'for User-Agent header')
|
||||
parser.add_argument('--project', dest='project_name',
|
||||
help='optional project name; will auto-discover by default')
|
||||
parser.add_argument('--key', dest='key',
|
||||
help='your wakatime api key; uses api_key from '+
|
||||
'~/.wakatime.conf by default')
|
||||
parser.add_argument('--write', dest='isWrite',
|
||||
action='store_true',
|
||||
help='when set, tells api this heartbeat was triggered from '+
|
||||
'writing to a file')
|
||||
parser.add_argument('--plugin', dest='plugin',
|
||||
help='optional text editor plugin name and version '+
|
||||
'for User-Agent header')
|
||||
parser.add_argument('--time', dest='timestamp', metavar='time',
|
||||
type=float,
|
||||
help='optional floating-point unix epoch timestamp; '+
|
||||
'uses current time by default')
|
||||
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('--proxy', dest='proxy',
|
||||
help='optional https proxy url; for example: '+
|
||||
'https://user:pass@localhost:8080')
|
||||
parser.add_argument('--project', dest='project_name',
|
||||
help='optional project name; will auto-discover by default')
|
||||
parser.add_argument('--disableoffline', dest='offline',
|
||||
action='store_false',
|
||||
help='disables offline time logging instead of queuing logged time')
|
||||
parser.add_argument('--hidefilenames', dest='hidefilenames',
|
||||
action='store_true',
|
||||
help='obfuscate file names; will not send file names to api')
|
||||
parser.add_argument('--exclude', dest='exclude', action='append',
|
||||
help='filename patterns to exclude from logging; POSIX regex '+
|
||||
'syntax; can be used more than once')
|
||||
parser.add_argument('--include', dest='include', action='append',
|
||||
help='filename patterns to log; when used in combination with '+
|
||||
'--exclude, files matching include will still be logged; '+
|
||||
'POSIX regex syntax; can be used more than once')
|
||||
parser.add_argument('--ignore', dest='ignore', action='append',
|
||||
help='filename patterns to ignore; POSIX regex syntax; can be used more than once')
|
||||
help=argparse.SUPPRESS)
|
||||
parser.add_argument('--logfile', dest='logfile',
|
||||
help='defaults to ~/.wakatime.log')
|
||||
parser.add_argument('--config', dest='config',
|
||||
|
@ -191,23 +195,43 @@ def parseArguments(argv):
|
|||
default_key = None
|
||||
if configs.has_option('settings', 'api_key'):
|
||||
default_key = configs.get('settings', 'api_key')
|
||||
elif configs.has_option('settings', 'apikey'):
|
||||
default_key = configs.get('settings', 'apikey')
|
||||
if default_key:
|
||||
args.key = default_key
|
||||
else:
|
||||
parser.error('Missing api key')
|
||||
if not args.ignore:
|
||||
args.ignore = []
|
||||
if not args.exclude:
|
||||
args.exclude = []
|
||||
if configs.has_option('settings', 'ignore'):
|
||||
try:
|
||||
for pattern in configs.get('settings', 'ignore').split("\n"):
|
||||
if pattern.strip() != '':
|
||||
args.ignore.append(pattern)
|
||||
args.exclude.append(pattern)
|
||||
except TypeError:
|
||||
pass
|
||||
if configs.has_option('settings', 'exclude'):
|
||||
try:
|
||||
for pattern in configs.get('settings', 'exclude').split("\n"):
|
||||
if pattern.strip() != '':
|
||||
args.exclude.append(pattern)
|
||||
except TypeError:
|
||||
pass
|
||||
if not args.include:
|
||||
args.include = []
|
||||
if configs.has_option('settings', 'include'):
|
||||
try:
|
||||
for pattern in configs.get('settings', 'include').split("\n"):
|
||||
if pattern.strip() != '':
|
||||
args.include.append(pattern)
|
||||
except TypeError:
|
||||
pass
|
||||
if args.offline and configs.has_option('settings', 'offline'):
|
||||
args.offline = configs.getboolean('settings', 'offline')
|
||||
if not args.hidefilenames and configs.has_option('settings', 'hidefilenames'):
|
||||
args.hidefilenames = configs.getboolean('settings', 'hidefilenames')
|
||||
if not args.proxy and configs.has_option('settings', 'proxy'):
|
||||
args.proxy = configs.get('settings', 'proxy')
|
||||
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'):
|
||||
|
@ -218,20 +242,34 @@ def parseArguments(argv):
|
|||
return args, configs
|
||||
|
||||
|
||||
def should_ignore(fileName, patterns):
|
||||
try:
|
||||
for pattern in patterns:
|
||||
try:
|
||||
compiled = re.compile(pattern, re.IGNORECASE)
|
||||
if compiled.search(fileName):
|
||||
return pattern
|
||||
except re.error as ex:
|
||||
log.warning(u('Regex error ({msg}) for ignore pattern: {pattern}').format(
|
||||
msg=u(ex),
|
||||
pattern=u(pattern),
|
||||
))
|
||||
except TypeError:
|
||||
pass
|
||||
def should_exclude(fileName, include, exclude):
|
||||
if fileName is not None and fileName.strip() != '':
|
||||
try:
|
||||
for pattern in include:
|
||||
try:
|
||||
compiled = re.compile(pattern, re.IGNORECASE)
|
||||
if compiled.search(fileName):
|
||||
return False
|
||||
except re.error as ex:
|
||||
log.warning(u('Regex error ({msg}) for include pattern: {pattern}').format(
|
||||
msg=u(ex),
|
||||
pattern=u(pattern),
|
||||
))
|
||||
except TypeError:
|
||||
pass
|
||||
try:
|
||||
for pattern in exclude:
|
||||
try:
|
||||
compiled = re.compile(pattern, re.IGNORECASE)
|
||||
if compiled.search(fileName):
|
||||
return pattern
|
||||
except re.error as ex:
|
||||
log.warning(u('Regex error ({msg}) for exclude pattern: {pattern}').format(
|
||||
msg=u(ex),
|
||||
pattern=u(pattern),
|
||||
))
|
||||
except TypeError:
|
||||
pass
|
||||
return False
|
||||
|
||||
|
||||
|
@ -248,19 +286,23 @@ def get_user_agent(plugin):
|
|||
user_agent=user_agent,
|
||||
plugin=u(plugin),
|
||||
)
|
||||
else:
|
||||
user_agent = u('{user_agent} Unknown/0').format(
|
||||
user_agent=user_agent,
|
||||
)
|
||||
return user_agent
|
||||
|
||||
|
||||
def send_heartbeat(project=None, branch=None, stats={}, key=None, targetFile=None,
|
||||
timestamp=None, isWrite=None, plugin=None, offline=None,
|
||||
hidefilenames=None, **kwargs):
|
||||
hidefilenames=None, notfile=False, proxy=None, **kwargs):
|
||||
url = 'https://wakatime.com/api/v1/heartbeats'
|
||||
log.debug('Sending heartbeat to api at %s' % url)
|
||||
data = {
|
||||
'time': timestamp,
|
||||
'file': targetFile,
|
||||
}
|
||||
if hidefilenames and targetFile is not None:
|
||||
if hidefilenames and targetFile is not None and not notfile:
|
||||
data['file'] = data['file'].rsplit('/', 1)[-1].rsplit('\\', 1)[-1]
|
||||
if len(data['file'].strip('.').split('.', 1)) > 1:
|
||||
data['file'] = u('HIDDEN.{ext}').format(ext=u(data['file'].strip('.').rsplit('.', 1)[-1]))
|
||||
|
@ -282,15 +324,17 @@ def send_heartbeat(project=None, branch=None, stats={}, key=None, targetFile=Non
|
|||
|
||||
# setup api request
|
||||
request_body = json.dumps(data)
|
||||
request = Request(url=url, data=str.encode(request_body) if is_py3 else request_body)
|
||||
request.add_header('User-Agent', get_user_agent(plugin))
|
||||
request.add_header('Content-Type', 'application/json')
|
||||
auth = u('Basic {key}').format(key=u(base64.b64encode(str.encode(key) if is_py3 else key)))
|
||||
request.add_header('Authorization', auth)
|
||||
|
||||
ALWAYS_LOG_CODES = [
|
||||
401,
|
||||
]
|
||||
api_key = u(base64.b64encode(str.encode(key) if is_py3 else key))
|
||||
auth = u('Basic {api_key}').format(api_key=api_key)
|
||||
headers = {
|
||||
'User-Agent': get_user_agent(plugin),
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
'Authorization': auth,
|
||||
}
|
||||
proxies = {}
|
||||
if proxy:
|
||||
proxies['https'] = proxy
|
||||
|
||||
# add Olson timezone to request
|
||||
try:
|
||||
|
@ -298,68 +342,48 @@ def send_heartbeat(project=None, branch=None, stats={}, key=None, targetFile=Non
|
|||
except:
|
||||
tz = None
|
||||
if tz:
|
||||
request.add_header('TimeZone', u(tz.zone))
|
||||
headers['TimeZone'] = u(tz.zone)
|
||||
|
||||
# log time to api
|
||||
response = None
|
||||
try:
|
||||
response = urlopen(request)
|
||||
except HTTPError as exc:
|
||||
response = requests.post(url, data=request_body, headers=headers,
|
||||
proxies=proxies)
|
||||
except RequestException:
|
||||
exception_data = {
|
||||
'response_code': exc.getcode(),
|
||||
sys.exc_info()[0].__name__: u(sys.exc_info()[1]),
|
||||
}
|
||||
if log.isEnabledFor(logging.DEBUG):
|
||||
exception_data['traceback'] = traceback.format_exc()
|
||||
if offline:
|
||||
if response is None or response.getcode() != 400:
|
||||
queue = Queue()
|
||||
queue.push(data, json.dumps(stats), plugin)
|
||||
queue = Queue()
|
||||
queue.push(data, json.dumps(stats), plugin)
|
||||
if log.isEnabledFor(logging.DEBUG):
|
||||
log.warn(exception_data)
|
||||
if response is not None and response.getcode() in ALWAYS_LOG_CODES:
|
||||
log.error({
|
||||
'response_code': response.getcode(),
|
||||
})
|
||||
else:
|
||||
log.error(exception_data)
|
||||
except:
|
||||
exception_data = {
|
||||
sys.exc_info()[0].__name__: u(sys.exc_info()[1]),
|
||||
}
|
||||
if log.isEnabledFor(logging.DEBUG):
|
||||
exception_data['traceback'] = traceback.format_exc()
|
||||
if offline:
|
||||
if response is None or response.getcode() != 400:
|
||||
queue = Queue()
|
||||
queue.push(data, json.dumps(stats), plugin)
|
||||
if 'unknown url type: https' in u(sys.exc_info()[1]):
|
||||
log.error(exception_data)
|
||||
elif log.isEnabledFor(logging.DEBUG):
|
||||
log.warn(exception_data)
|
||||
if response is not None and response.getcode() in ALWAYS_LOG_CODES:
|
||||
log.error({
|
||||
'response_code': response.getcode(),
|
||||
})
|
||||
else:
|
||||
log.error(exception_data)
|
||||
else:
|
||||
if response is not None and response.getcode() == 201:
|
||||
response_code = response.status_code if response is not None else None
|
||||
response_content = response.text if response is not None else None
|
||||
if response_code == 201:
|
||||
log.debug({
|
||||
'response_code': response.getcode(),
|
||||
'response_code': response_code,
|
||||
})
|
||||
return True
|
||||
response_code = response.getcode() if response is not None else None
|
||||
response_content = response.read() if response is not None else None
|
||||
if offline:
|
||||
if response is None or response.getcode() != 400:
|
||||
if response_code != 400:
|
||||
queue = Queue()
|
||||
queue.push(data, json.dumps(stats), plugin)
|
||||
if log.isEnabledFor(logging.DEBUG):
|
||||
log.warn({
|
||||
'response_code': response_code,
|
||||
'response_content': response_content,
|
||||
})
|
||||
if response_code == 401:
|
||||
log.error({
|
||||
'response_code': response_code,
|
||||
'response_content': response_content,
|
||||
})
|
||||
elif log.isEnabledFor(logging.DEBUG):
|
||||
log.warn({
|
||||
'response_code': response_code,
|
||||
'response_content': response_content,
|
||||
})
|
||||
else:
|
||||
log.error({
|
||||
'response_code': response_code,
|
||||
|
@ -383,18 +407,20 @@ def main(argv=None):
|
|||
|
||||
setup_logging(args, __version__)
|
||||
|
||||
ignore = should_ignore(args.targetFile, args.ignore)
|
||||
if ignore is not False:
|
||||
log.debug(u('File ignored because matches pattern: {pattern}').format(
|
||||
pattern=u(ignore),
|
||||
exclude = should_exclude(args.targetFile, args.include, args.exclude)
|
||||
if exclude is not False:
|
||||
log.debug(u('File not logged because matches exclude pattern: {pattern}').format(
|
||||
pattern=u(exclude),
|
||||
))
|
||||
return 0
|
||||
|
||||
if os.path.isfile(args.targetFile):
|
||||
if os.path.isfile(args.targetFile) or args.notfile:
|
||||
|
||||
stats = get_file_stats(args.targetFile)
|
||||
stats = get_file_stats(args.targetFile, notfile=args.notfile)
|
||||
|
||||
project = find_project(args.targetFile, configs=configs)
|
||||
project = None
|
||||
if not args.notfile:
|
||||
project = find_project(args.targetFile, configs=configs)
|
||||
branch = None
|
||||
project_name = args.project_name
|
||||
if project:
|
||||
|
@ -421,7 +447,9 @@ def main(argv=None):
|
|||
isWrite=heartbeat['is_write'],
|
||||
plugin=heartbeat['plugin'],
|
||||
offline=args.offline,
|
||||
hidefilenames=args.hidefilenames)
|
||||
hidefilenames=args.hidefilenames,
|
||||
notfile=args.notfile,
|
||||
proxy=args.proxy)
|
||||
if not sent:
|
||||
break
|
||||
return 0 # success
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
wakatime-cli
|
||||
wakatime.cli
|
||||
~~~~~~~~~~~~
|
||||
|
||||
Command-line entry point.
|
||||
|
@ -9,11 +9,9 @@
|
|||
:license: BSD, see LICENSE for more details.
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import sys
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
import wakatime
|
||||
|
||||
if __name__ == '__main__':
|
|
@ -12,7 +12,6 @@
|
|||
import os
|
||||
|
||||
from . import TokenParser
|
||||
from ..compat import u
|
||||
|
||||
|
||||
FILES = {
|
|
@ -30,7 +30,6 @@ class CustomEncoder(json.JSONEncoder):
|
|||
try:
|
||||
encoded = super(CustomEncoder, self).default(obj)
|
||||
except UnicodeDecodeError:
|
||||
encoding = sys.getfilesystemencoding()
|
||||
obj = u(obj)
|
||||
encoded = super(CustomEncoder, self).default(obj)
|
||||
return encoded
|
||||
|
@ -63,7 +62,7 @@ class JsonFormatter(logging.Formatter):
|
|||
return CustomEncoder().encode(data)
|
||||
|
||||
def formatException(self, exc_info):
|
||||
return exec_info[2].format_exc()
|
||||
return sys.exec_info[2].format_exc()
|
||||
|
||||
|
||||
def set_log_level(logger, args):
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue