From bd5e87e0309d27f30725d6a7ae49b0966b76488a Mon Sep 17 00:00:00 2001 From: Alan Hamlett Date: Tue, 7 May 2019 18:42:31 -0700 Subject: [PATCH] upgrade wakatime-cli to v11.0.0 --- packages/wakatime/__about__.py | 2 +- packages/wakatime/api.py | 113 +++++++++++++++++++++++++++++++++ packages/wakatime/arguments.py | 5 +- packages/wakatime/main.py | 8 ++- 4 files changed, 125 insertions(+), 3 deletions(-) diff --git a/packages/wakatime/__about__.py b/packages/wakatime/__about__.py index d1b4fc8..1dbd215 100644 --- a/packages/wakatime/__about__.py +++ b/packages/wakatime/__about__.py @@ -1,7 +1,7 @@ __title__ = 'wakatime' __description__ = 'Common interface to the WakaTime api.' __url__ = 'https://github.com/wakatime/wakatime' -__version_info__ = ('10', '8', '4') +__version_info__ = ('11', '0', '0') __version__ = '.'.join(__version_info__) __author__ = 'Alan Hamlett' __author_email__ = 'alan@wakatime.com' diff --git a/packages/wakatime/api.py b/packages/wakatime/api.py index a98ebeb..16286a4 100644 --- a/packages/wakatime/api.py +++ b/packages/wakatime/api.py @@ -163,6 +163,119 @@ def send_heartbeats(heartbeats, args, configs, use_ntlm_proxy=False): return AUTH_ERROR if code == 401 else API_ERROR +def get_time_today(args, use_ntlm_proxy=False): + """Get coding time from WakaTime API for given time range. + + Returns total time as string or `None` when unable to fetch summary from + the API. When verbose output enabled, returns error message when unable to + fetch summary. + """ + + url = 'https://api.wakatime.com/api/v1/users/current/summaries' + timeout = args.timeout + if not timeout: + timeout = 60 + + api_key = u(base64.b64encode(str.encode(args.key) if is_py3 else args.key)) + auth = u('Basic {api_key}').format(api_key=api_key) + headers = { + 'User-Agent': get_user_agent(args.plugin), + 'Accept': 'application/json', + 'Authorization': auth, + } + + session_cache = SessionCache() + session = session_cache.get() + + should_try_ntlm = False + proxies = {} + if args.proxy: + if use_ntlm_proxy: + from .packages.requests_ntlm import HttpNtlmAuth + username = args.proxy.rsplit(':', 1) + password = '' + if len(username) == 2: + password = username[1] + username = username[0] + session.auth = HttpNtlmAuth(username, password, session) + else: + should_try_ntlm = '\\' in args.proxy + proxies['https'] = args.proxy + + ssl_verify = not args.nosslverify + if args.ssl_certs_file and ssl_verify: + ssl_verify = args.ssl_certs_file + + params = { + 'start': 'today', + 'end': 'today', + } + + # send request to api + response, code = None, None + try: + response = session.get(url, params=params, headers=headers, + proxies=proxies, timeout=timeout, + verify=ssl_verify) + except RequestException: + if should_try_ntlm: + return get_time_today(args, use_ntlm_proxy=True) + + session_cache.delete() + if log.isEnabledFor(logging.DEBUG): + exception_data = { + sys.exc_info()[0].__name__: u(sys.exc_info()[1]), + 'traceback': traceback.format_exc(), + } + log.error(exception_data) + return '{0}: {1}'.format(sys.exc_info()[0].__name__, u(sys.exc_info()[1])), API_ERROR + return None, API_ERROR + + except: # delete cached session when requests raises unknown exception + if should_try_ntlm: + return get_time_today(args, use_ntlm_proxy=True) + + session_cache.delete() + if log.isEnabledFor(logging.DEBUG): + exception_data = { + sys.exc_info()[0].__name__: u(sys.exc_info()[1]), + 'traceback': traceback.format_exc(), + } + log.error(exception_data) + return '{0}: {1}'.format(sys.exc_info()[0].__name__, u(sys.exc_info()[1])), API_ERROR + return None, API_ERROR + + 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.ok: + try: + text = response.json()['data'][0]['grand_total']['text'] + session_cache.save(session) + return text, SUCCESS + except: + if log.isEnabledFor(logging.DEBUG): + exception_data = { + sys.exc_info()[0].__name__: u(sys.exc_info()[1]), + 'traceback': traceback.format_exc(), + } + log.error(exception_data) + return '{0}: {1}'.format(sys.exc_info()[0].__name__, u(sys.exc_info()[1])), API_ERROR + return None, API_ERROR + else: + if should_try_ntlm: + return get_time_today(args, use_ntlm_proxy=True) + + session_cache.delete() + log.debug({ + 'response_code': code, + 'response_text': content, + }) + if log.isEnabledFor(logging.DEBUG): + return 'Error: {0}'.format(code), API_ERROR + return None, API_ERROR + + def _process_server_results(heartbeats, code, content, results, args, configs): log.debug({ 'response_code': code, diff --git a/packages/wakatime/arguments.py b/packages/wakatime/arguments.py index d02b57a..035127d 100644 --- a/packages/wakatime/arguments.py +++ b/packages/wakatime/arguments.py @@ -201,6 +201,9 @@ def parse_arguments(): 'online 5 offline heartbeats are synced. Can ' + 'be used without --entity to only sync offline ' + 'activity without generating new heartbeats.') + parser.add_argument('--today', dest='today', + action='store_true', + help='Prints dashboard time for Today, then exits.') parser.add_argument('--config', dest='config', action=StoreWithoutQuotes, help='Defaults to ~/.wakatime.cfg.') parser.add_argument('--verbose', dest='verbose', action='store_true', @@ -245,7 +248,7 @@ def parse_arguments(): if not args.entity: if args.file: args.entity = args.file - elif not args.sync_offline_activity or args.sync_offline_activity == 'none': + elif (not args.sync_offline_activity or args.sync_offline_activity == 'none') and not args.today: parser.error('argument --entity is required') if not args.sync_offline_activity: diff --git a/packages/wakatime/main.py b/packages/wakatime/main.py index a1a6dca..02a40dc 100644 --- a/packages/wakatime/main.py +++ b/packages/wakatime/main.py @@ -22,7 +22,7 @@ sys.path.insert(0, os.path.dirname(pwd)) sys.path.insert(0, os.path.join(pwd, 'packages')) from .__about__ import __version__ -from .api import send_heartbeats +from .api import send_heartbeats, get_time_today from .arguments import parse_arguments from .compat import u, json from .constants import SUCCESS, UNKNOWN_ERROR, HEARTBEATS_PER_REQUEST @@ -42,6 +42,12 @@ def execute(argv=None): setup_logging(args, __version__) + if args.today: + text, retval = get_time_today(args) + if text: + print(text) + return retval + try: heartbeats = []