upgrade wakatime-cli to v4.1.11

This commit is contained in:
Alan Hamlett 2016-03-06 12:48:42 -08:00
parent 90731146f9
commit 3ce8f388ab
14 changed files with 139 additions and 81 deletions

View file

@ -1,7 +1,7 @@
__title__ = 'wakatime'
__description__ = 'Common interface to the WakaTime api.'
__url__ = 'https://github.com/wakatime/wakatime'
__version_info__ = ('4', '1', '10')
__version_info__ = ('4', '1', '11')
__version__ = '.'.join(__version_info__)
__author__ = 'Alan Hamlett'
__author_email__ = 'alan@wakatime.com'

View file

@ -13,3 +13,4 @@
SUCCESS = 0
API_ERROR = 102
CONFIG_FILE_PARSE_ERROR = 103
AUTH_ERROR = 104

View file

@ -73,6 +73,13 @@ class JsonFormatter(logging.Formatter):
def traceback_formatter(*args, **kwargs):
if 'level' in kwargs and (kwargs['level'].lower() == 'warn' or kwargs['level'].lower() == 'warning'):
logging.getLogger('WakaTime').warning(traceback.format_exc())
elif 'level' in kwargs and kwargs['level'].lower() == 'info':
logging.getLogger('WakaTime').info(traceback.format_exc())
elif 'level' in kwargs and kwargs['level'].lower() == 'debug':
logging.getLogger('WakaTime').debug(traceback.format_exc())
else:
logging.getLogger('WakaTime').error(traceback.format_exc())

View file

@ -25,12 +25,18 @@ try:
except ImportError: # pragma: nocover
import configparser
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), 'packages'))
pwd = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, os.path.dirname(pwd))
sys.path.insert(0, os.path.join(pwd, 'packages'))
from .__about__ import __version__
from .compat import u, open, is_py3
from .constants import SUCCESS, API_ERROR, CONFIG_FILE_PARSE_ERROR
from .constants import (
API_ERROR,
AUTH_ERROR,
CONFIG_FILE_PARSE_ERROR,
SUCCESS,
)
from .logger import setup_logging
from .offlinequeue import Queue
from .packages import argparse
@ -127,8 +133,10 @@ def parseArguments():
parser.add_argument('--project', dest='project',
help='optional project name')
parser.add_argument('--alternate-project', dest='alternate_project',
help='optional alternate project name; auto-discovered project takes priority')
parser.add_argument('--hostname', dest='hostname', help='hostname of current machine.')
help='optional alternate project name; auto-discovered project '+
'takes priority')
parser.add_argument('--hostname', dest='hostname', help='hostname of '+
'current machine.')
parser.add_argument('--disableoffline', dest='offline',
action='store_false',
help='disables offline time logging instead of queuing logged time')
@ -285,10 +293,14 @@ def get_user_agent(plugin):
return user_agent
def send_heartbeat(project=None, branch=None, hostname=None, stats={}, key=None, entity=None,
timestamp=None, isWrite=None, plugin=None, offline=None, entity_type='file',
hidefilenames=None, proxy=None, api_url=None, timeout=None, **kwargs):
def send_heartbeat(project=None, branch=None, hostname=None, stats={}, key=None,
entity=None, timestamp=None, isWrite=None, plugin=None,
offline=None, entity_type='file', hidefilenames=None,
proxy=None, api_url=None, timeout=None, **kwargs):
"""Sends heartbeat as POST request to WakaTime api server.
Returns `SUCCESS` when heartbeat was sent, otherwise returns an
error code constant.
"""
if not api_url:
@ -333,7 +345,7 @@ def send_heartbeat(project=None, branch=None, hostname=None, stats={}, key=None,
'Authorization': auth,
}
if hostname:
headers['X-Machine-Name'] = hostname
headers['X-Machine-Name'] = u(hostname)
proxies = {}
if proxy:
proxies['https'] = proxy
@ -368,40 +380,74 @@ def send_heartbeat(project=None, branch=None, hostname=None, stats={}, key=None,
else:
log.error(exception_data)
else:
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 == requests.codes.created or response_code == requests.codes.accepted:
code = response.status_code if response is not None else None
content = response.text if response is not None else None
if code == requests.codes.created or code == requests.codes.accepted:
log.debug({
'response_code': response_code,
'response_code': code,
})
session_cache.save(session)
return True
return SUCCESS
if offline:
if response_code != 400:
if code != 400:
queue = Queue()
queue.push(data, json.dumps(stats), plugin)
if response_code == 401:
if 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,
'response_content': response_content,
})
else:
log.error({
'response_code': response_code,
'response_content': response_content,
'response_code': code,
'response_content': content,
})
session_cache.delete()
return False
return AUTH_ERROR
elif log.isEnabledFor(logging.DEBUG):
log.warn({
'response_code': code,
'response_content': content,
})
else:
log.error({
'response_code': code,
'response_content': content,
})
else:
log.error({
'response_code': code,
'response_content': content,
})
session_cache.delete()
return API_ERROR
def sync_offline_heartbeats(args, hostname):
"""Sends all heartbeats which were cached in the offline Queue."""
queue = Queue()
while True:
heartbeat = queue.pop()
if heartbeat is None:
break
status = send_heartbeat(
project=heartbeat['project'],
entity=heartbeat['entity'],
timestamp=heartbeat['time'],
branch=heartbeat['branch'],
hostname=hostname,
stats=json.loads(heartbeat['stats']),
key=args.key,
isWrite=heartbeat['is_write'],
plugin=heartbeat['plugin'],
offline=args.offline,
hidefilenames=args.hidefilenames,
entity_type=heartbeat['type'],
proxy=args.proxy,
api_url=args.api_url,
timeout=args.timeout,
)
if status != SUCCESS:
if status == AUTH_ERROR:
return AUTH_ERROR
break
return SUCCESS
def execute(argv=None):
@ -438,37 +484,15 @@ def execute(argv=None):
kwargs['project'] = project
kwargs['branch'] = branch
kwargs['stats'] = stats
kwargs['hostname'] = args.hostname or socket.gethostname()
hostname = args.hostname or socket.gethostname()
kwargs['hostname'] = hostname
kwargs['timeout'] = args.timeout
if send_heartbeat(**kwargs):
queue = Queue()
while True:
heartbeat = queue.pop()
if heartbeat is None:
break
sent = send_heartbeat(
project=heartbeat['project'],
entity=heartbeat['entity'],
timestamp=heartbeat['time'],
branch=heartbeat['branch'],
hostname=kwargs['hostname'],
stats=json.loads(heartbeat['stats']),
key=args.key,
isWrite=heartbeat['is_write'],
plugin=heartbeat['plugin'],
offline=args.offline,
hidefilenames=args.hidefilenames,
entity_type=heartbeat['type'],
proxy=args.proxy,
api_url=args.api_url,
timeout=args.timeout,
)
if not sent:
break
return SUCCESS
return API_ERROR
status = send_heartbeat(**kwargs)
if status == SUCCESS:
return sync_offline_heartbeats(args, hostname)
else:
return status
else:
log.debug('File does not exist; ignoring this heartbeat.')

View file

@ -46,7 +46,7 @@ __version__ = '2.9.1'
__build__ = 0x020901
__author__ = 'Kenneth Reitz'
__license__ = 'Apache 2.0'
__copyright__ = 'Copyright 2015 Kenneth Reitz'
__copyright__ = 'Copyright 2016 Kenneth Reitz'
# Attempt to enable urllib3's SNI support, if possible
try:

View file

@ -65,7 +65,7 @@ class HTTPAdapter(BaseAdapter):
:param pool_connections: The number of urllib3 connection pools to cache.
:param pool_maxsize: The maximum number of connections to save in the pool.
:param int max_retries: The maximum number of retries each connection
:param max_retries: The maximum number of retries each connection
should attempt. Note, this applies only to failed DNS lookups, socket
connections and connection timeouts, never to requests where data has
made it to the server. By default, Requests does not retry failed

View file

@ -47,6 +47,15 @@ class HTTPBasicAuth(AuthBase):
self.username = username
self.password = password
def __eq__(self, other):
return all([
self.username == getattr(other, 'username', None),
self.password == getattr(other, 'password', None)
])
def __ne__(self, other):
return not self == other
def __call__(self, r):
r.headers['Authorization'] = _basic_auth_str(self.username, self.password)
return r
@ -221,3 +230,12 @@ class HTTPDigestAuth(AuthBase):
self._thread_local.num_401_calls = 1
return r
def __eq__(self, other):
return all([
self.username == getattr(other, 'username', None),
self.password == getattr(other, 'password', None)
])
def __ne__(self, other):
return not self == other

View file

@ -277,6 +277,12 @@ class RequestsCookieJar(cookielib.CookieJar, collections.MutableMapping):
dictionary[cookie.name] = cookie.value
return dictionary
def __contains__(self, name):
try:
return super(RequestsCookieJar, self).__contains__(name)
except CookieConflictError:
return True
def __getitem__(self, name):
"""Dict-like __getitem__() for compatibility with client code. Throws
exception if there are more than one cookie with name. In that case,

View file

@ -110,7 +110,7 @@ class SessionRedirectMixin(object):
resp.raw.read(decode_content=False)
if i >= self.max_redirects:
raise TooManyRedirects('Exceeded %s redirects.' % self.max_redirects)
raise TooManyRedirects('Exceeded %s redirects.' % self.max_redirects, response=resp)
# Release the connection back into the pool.
resp.close()
@ -553,6 +553,13 @@ class Session(SessionRedirectMixin):
if not isinstance(request, PreparedRequest):
raise ValueError('You can only send PreparedRequests.')
# Set up variables needed for resolve_redirects and dispatching of hooks
allow_redirects = kwargs.pop('allow_redirects', True)
stream = kwargs.get('stream')
hooks = request.hooks
# Resolve URL in redirect cache, if available.
if allow_redirects:
checked_urls = set()
while request.url in self.redirect_cache:
checked_urls.add(request.url)
@ -561,11 +568,6 @@ class Session(SessionRedirectMixin):
break
request.url = new_url
# Set up variables needed for resolve_redirects and dispatching of hooks
allow_redirects = kwargs.pop('allow_redirects', True)
stream = kwargs.get('stream')
hooks = request.hooks
# Get the appropriate adapter to use
adapter = self.get_adapter(url=request.url)

View file

@ -44,9 +44,9 @@ class Git(BaseProject):
with open(head, 'r', encoding=sys.getfilesystemencoding()) as fh:
return u(fh.readline().strip().rsplit('/', 1)[-1])
except:
log.traceback()
log.traceback('warn')
except IOError: # pragma: nocover
log.traceback()
log.traceback('warn')
return None
def _project_base(self):

View file

@ -42,9 +42,9 @@ class Mercurial(BaseProject):
with open(branch_file, 'r', encoding=sys.getfilesystemencoding()) as fh:
return u(fh.readline().strip().rsplit('/', 1)[-1])
except:
log.traceback()
log.traceback('warn')
except IOError: # pragma: nocover
log.traceback()
log.traceback('warn')
return u('default')
def _find_hg_config_dir(self, path):

View file

@ -41,9 +41,9 @@ class WakaTimeProjectFile(BaseProject):
self._project_name = u(fh.readline().strip())
self._project_branch = u(fh.readline().strip())
except:
log.traceback()
log.traceback('warn')
except IOError: # pragma: nocover
log.traceback()
log.traceback('warn')
return True
return False

View file

@ -57,7 +57,7 @@ class SessionCache(object):
conn.commit()
conn.close()
except: # pragma: nocover
log.traceback()
log.traceback('debug')
def get(self):
@ -72,7 +72,7 @@ class SessionCache(object):
try:
conn, c = self.connect()
except:
log.traceback()
log.traceback('debug')
return requests.session()
session = None
@ -83,12 +83,12 @@ class SessionCache(object):
if row is not None:
session = pickle.loads(row[0])
except: # pragma: nocover
log.traceback()
log.traceback('debug')
try:
conn.close()
except: # pragma: nocover
log.traceback()
log.traceback('debug')
return session if session is not None else requests.session()
@ -105,4 +105,4 @@ class SessionCache(object):
conn.commit()
conn.close()
except:
log.traceback()
log.traceback('debug')

View file

@ -191,5 +191,5 @@ def get_file_contents(file_name):
with open(file_name, 'r', encoding=sys.getfilesystemencoding()) as fh:
text = fh.read(512000)
except:
log.traceback()
log.traceback('debug')
return text