From 4de44fbd544048a66d5c7075bd77162cca7139b7 Mon Sep 17 00:00:00 2001 From: Giovanni <5774411+giovannicoppola@users.noreply.github.com> Date: Wed, 18 May 2022 16:10:36 -0400 Subject: [PATCH] 1.99.1 --- releases/ZotHero1-99-1.alfredworkflow | Bin 0 -> 519972 bytes src/info.plist | 122 +- src/lib/.DS_Store | Bin 6148 -> 6148 bytes src/lib/workflow_old/.DS_Store | Bin 6148 -> 0 bytes src/lib/workflow_old/Notify.tgz | Bin 35556 -> 0 bytes src/lib/workflow_old/__init__.py | 109 - src/lib/workflow_old/background.py | 295 -- src/lib/workflow_old/notify.py | 346 --- src/lib/workflow_old/update.py | 434 --- src/lib/workflow_old/update_old.py | 565 ---- src/lib/workflow_old/util.py | 552 ---- src/lib/workflow_old/version | 1 - src/lib/workflow_old/web.py | 677 ----- src/lib/workflow_old/web_old.py | 685 ----- src/lib/workflow_old/workflow.py | 2817 ------------------- src/lib/workflow_old/workflow3.py | 721 ----- src/lib/workflow_old/workflow_old.py | 2821 ------------------- src/lib/xp_workflow/.alfredversionchecked | 0 src/lib/xp_workflow/__init__.py | 97 - src/lib/xp_workflow/background.py | 284 -- src/lib/xp_workflow/notificator | 169 -- src/lib/xp_workflow/notify.py | 92 - src/lib/xp_workflow/update.py | 544 ---- src/lib/xp_workflow/util.py | 519 ---- src/lib/xp_workflow/version | 1 - src/lib/xp_workflow/web.py | 750 ----- src/lib/xp_workflow/workflow.py | 3109 --------------------- src/lib/zothero/core.py | 2 +- 28 files changed, 121 insertions(+), 15591 deletions(-) create mode 100644 releases/ZotHero1-99-1.alfredworkflow delete mode 100644 src/lib/workflow_old/.DS_Store delete mode 100644 src/lib/workflow_old/Notify.tgz delete mode 100644 src/lib/workflow_old/__init__.py delete mode 100644 src/lib/workflow_old/background.py delete mode 100644 src/lib/workflow_old/notify.py delete mode 100644 src/lib/workflow_old/update.py delete mode 100644 src/lib/workflow_old/update_old.py delete mode 100644 src/lib/workflow_old/util.py delete mode 100644 src/lib/workflow_old/version delete mode 100644 src/lib/workflow_old/web.py delete mode 100644 src/lib/workflow_old/web_old.py delete mode 100644 src/lib/workflow_old/workflow.py delete mode 100644 src/lib/workflow_old/workflow3.py delete mode 100644 src/lib/workflow_old/workflow_old.py delete mode 100644 src/lib/xp_workflow/.alfredversionchecked delete mode 100644 src/lib/xp_workflow/__init__.py delete mode 100644 src/lib/xp_workflow/background.py delete mode 100755 src/lib/xp_workflow/notificator delete mode 100644 src/lib/xp_workflow/notify.py delete mode 100644 src/lib/xp_workflow/update.py delete mode 100644 src/lib/xp_workflow/util.py delete mode 100644 src/lib/xp_workflow/version delete mode 100644 src/lib/xp_workflow/web.py delete mode 100644 src/lib/xp_workflow/workflow.py diff --git a/releases/ZotHero1-99-1.alfredworkflow b/releases/ZotHero1-99-1.alfredworkflow new file mode 100644 index 0000000000000000000000000000000000000000..393f704206aece726ffb8a3ed12392d55503f8c9 GIT binary patch literal 519972 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 z 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�``PJb?M-~fCPqB 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 literal 0 HcmV?d00001 diff --git a/src/info.plist b/src/info.plist index c6230fc..57e935d 100644 --- a/src/info.plist +++ b/src/info.plist @@ -254,6 +254,16 @@ vitoclose + + destinationuid + C75ABE16-D510-4099-BE4B-7BB579DA8435 + modifiers + 0 + modifiersubtext + + vitoclose + + 5CFF0FD7-987C-4910-AD1E-0C40BF66585A @@ -1114,6 +1124,103 @@ python3 zh.py attachments $id "$1" version 1 + + config + + concurrently + + escaping + 0 + script + # THESE VARIABLES MUST BE SET. SEE THE ONEUPDATER README FOR AN EXPLANATION OF EACH. +readonly remote_info_plist='https://raw.githubusercontent.com/giovannicoppola/zothero/master/src/info.plist' +readonly workflow_url='https://github.com/giovannicoppola/zothero' +readonly download_type='github_release' +readonly frequency_check='1' + +# FROM HERE ON, CODE SHOULD BE LEFT UNTOUCHED! +function abort { + echo "${1}" >&2 + exit 1 +} + +function url_exists { + curl --silent --location --output /dev/null --fail --range 0-0 "${1}" +} + +function notification { + local -r notificator="$(find . -type f -name 'notificator')" + + if [[ -f "${notificator}" && "$(/usr/bin/file --brief --mime-type "${notificator}")" == 'text/x-shellscript' ]]; then + "${notificator}" --message "${1}" --title "${alfred_workflow_name}" --subtitle 'A new version is available' + return + fi + + osascript -e "display notification \"${1}\" with title \"${alfred_workflow_name}\" subtitle \"A new version is available\"" +} + +# Local sanity checks +readonly local_info_plist='info.plist' +readonly local_version="$(/usr/libexec/PlistBuddy -c 'print version' "${local_info_plist}")" + +[[ -n "${local_version}" ]] || abort 'You need to set a workflow version in the configuration sheet.' +[[ "${download_type}" =~ ^(direct|page|github_release)$ ]] || abort "'download_type' (${download_type}) needs to be one of 'direct', 'page', or 'github_release'." +[[ "${frequency_check}" =~ ^[0-9]+$ ]] || abort "'frequency_check' (${frequency_check}) needs to be a number." + +# Check for updates +if [[ $(find "${local_info_plist}" -mtime +"${frequency_check}"d) ]]; then + # Remote sanity check + if ! url_exists "${remote_info_plist}"; then + abort "'remote_info_plist' (${remote_info_plist}) appears to not be reachable." + fi + + readonly tmp_file="$(mktemp)" + curl --silent --location --output "${tmp_file}" "${remote_info_plist}" + readonly remote_version="$(/usr/libexec/PlistBuddy -c 'print version' "${tmp_file}")" + rm "${tmp_file}" + + if [[ "${local_version}" == "${remote_version}" ]]; then + touch "${local_info_plist}" # Reset timer by touching local file + exit 0 + fi + + if [[ "${download_type}" == 'page' ]]; then + notification 'Opening download page…' + open "${workflow_url}" + exit 0 + fi + + readonly download_url="$( + if [[ "${download_type}" == 'github_release' ]]; then + osascript -l JavaScript -e 'function run(argv) { return JSON.parse(argv[0])["assets"].find(asset => asset["browser_download_url"].endsWith(".alfredworkflow"))["browser_download_url"] }' "$(curl --silent "https://api.github.com/repos/${workflow_url}/releases/latest")" + else + echo "${workflow_url}" + fi + )" + + if url_exists "${download_url}"; then + notification 'Downloading and installing…' + readonly download_name="$(basename "${download_url}")" + curl --silent --location --output "${HOME}/Downloads/${download_name}" "${download_url}" + open "${HOME}/Downloads/${download_name}" + else + abort "'workflow_url' (${download_url}) appears to not be reachable." + fi +fi + scriptargtype + 1 + scriptfile + + type + 0 + + type + alfred.workflow.action.script + uid + C75ABE16-D510-4099-BE4B-7BB579DA8435 + version + 2 + config @@ -2439,6 +2546,17 @@ Edit the `ZOTERO_DIR` variable to point to Zotero 5's data directory if you aren ypos 875 + C75ABE16-D510-4099-BE4B-7BB579DA8435 + + colorindex + 12 + note + OneUpdater + xpos + 435 + ypos + 475 + C93018EF-4629-4261-B997-453D8F2D6856 colorindex @@ -2544,7 +2662,7 @@ Edit the `ZOTERO_DIR` variable to point to Zotero 5's data directory if you aren ATTACHMENTS_DIR CITE_STYLE - http://www.zotero.org/styles/nature + http://www.zotero.org/styles/elsevier-harvard COPY_CITEKEY_MOD LOCALE @@ -2560,7 +2678,7 @@ Edit the `ZOTERO_DIR` variable to point to Zotero 5's data directory if you aren COPY_CITEKEY_MOD version - 1.99 + 1.99.1 webaddress https://github.com/deanishe/zothero diff --git a/src/lib/.DS_Store b/src/lib/.DS_Store index d0214124bf929a8d8320b417100f4068d3299e40..0bbb9c30004b7344b4688fee8ea98972c2d8c7af 100644 GIT binary patch literal 6148 zcmeHKT~5O=40g(phQ`Al5l?yLaW^PcIl&G9>MB5@RVsco9(w~WwF7Vjj>2aX8(z!4ch z&1RX-6s=oteKqF58-~?t7^!Y8pF+O4*u~)CJzu~2NHo+2aT!~knX#>qTP3Y(`g7qM(!!2FVFGdl-A2T;l8iOk=b bC-aNwaxyY7FdP74hRHTO(wk#MmM{YV%D)nU diff --git a/src/lib/workflow_old/.DS_Store b/src/lib/workflow_old/.DS_Store deleted file mode 100644 index 5008ddfcf53c02e82d7eee2e57c38e5672ef89f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 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 diff --git a/src/lib/workflow_old/__init__.py b/src/lib/workflow_old/__init__.py deleted file mode 100644 index 9f2a32e..0000000 --- a/src/lib/workflow_old/__init__.py +++ /dev/null @@ -1,109 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# # -# Copyright (c) 2014 Dean Jackson -# -# MIT Licence. See http://opensource.org/licenses/MIT -# -# Created on 2014-02-15 -# - -"""A helper library for `Alfred `_ workflows.""" - -import os - -# Workflow objects -from .workflow import Workflow, manager -from .workflow3 import Variables, Workflow3 - -# Exceptions -from .workflow import PasswordNotFound, KeychainError - -# Icons -from .workflow import ( - ICON_ACCOUNT, - ICON_BURN, - ICON_CLOCK, - ICON_COLOR, - ICON_COLOUR, - ICON_EJECT, - ICON_ERROR, - ICON_FAVORITE, - ICON_FAVOURITE, - ICON_GROUP, - ICON_HELP, - ICON_HOME, - ICON_INFO, - ICON_NETWORK, - ICON_NOTE, - ICON_SETTINGS, - ICON_SWIRL, - ICON_SWITCH, - ICON_SYNC, - ICON_TRASH, - ICON_USER, - ICON_WARNING, - ICON_WEB, -) - -# Filter matching rules -from .workflow import ( - MATCH_ALL, - MATCH_ALLCHARS, - MATCH_ATOM, - MATCH_CAPITALS, - MATCH_INITIALS, - MATCH_INITIALS_CONTAIN, - MATCH_INITIALS_STARTSWITH, - MATCH_STARTSWITH, - MATCH_SUBSTRING, -) - - -__title__ = 'Alfred-Workflow' -__version__ = open(os.path.join(os.path.dirname(__file__), 'version')).read() -__author__ = 'Dean Jackson' -__licence__ = 'MIT' -__copyright__ = 'Copyright 2014-2019 Dean Jackson' - -__all__ = [ - 'Variables', - 'Workflow', - 'Workflow3', - 'manager', - 'PasswordNotFound', - 'KeychainError', - 'ICON_ACCOUNT', - 'ICON_BURN', - 'ICON_CLOCK', - 'ICON_COLOR', - 'ICON_COLOUR', - 'ICON_EJECT', - 'ICON_ERROR', - 'ICON_FAVORITE', - 'ICON_FAVOURITE', - 'ICON_GROUP', - 'ICON_HELP', - 'ICON_HOME', - 'ICON_INFO', - 'ICON_NETWORK', - 'ICON_NOTE', - 'ICON_SETTINGS', - 'ICON_SWIRL', - 'ICON_SWITCH', - 'ICON_SYNC', - 'ICON_TRASH', - 'ICON_USER', - 'ICON_WARNING', - 'ICON_WEB', - 'MATCH_ALL', - 'MATCH_ALLCHARS', - 'MATCH_ATOM', - 'MATCH_CAPITALS', - 'MATCH_INITIALS', - 'MATCH_INITIALS_CONTAIN', - 'MATCH_INITIALS_STARTSWITH', - 'MATCH_STARTSWITH', - 'MATCH_SUBSTRING', -] diff --git a/src/lib/workflow_old/background.py b/src/lib/workflow_old/background.py deleted file mode 100644 index b34cfda..0000000 --- a/src/lib/workflow_old/background.py +++ /dev/null @@ -1,295 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# -# Copyright (c) 2014 deanishe@deanishe.net -# -# MIT Licence. See http://opensource.org/licenses/MIT -# -# Created on 2014-04-06 -# - -"""This module provides an API to run commands in background processes. - -Combine with the :ref:`caching API ` to work from cached data -while you fetch fresh data in the background. - -See :ref:`the User Manual ` for more information -and examples. -""" - -from __future__ import print_function, unicode_literals - -import signal -import sys -import os -import subprocess -import pickle - -from workflow import Workflow - -__all__ = ['is_running', 'run_in_background'] - -_wf = None - - -def wf(): - global _wf - if _wf is None: - _wf = Workflow() - return _wf - - -def _log(): - return wf().logger - - -def _arg_cache(name): - """Return path to pickle cache file for arguments. - - :param name: name of task - :type name: ``unicode`` - :returns: Path to cache file - :rtype: ``unicode`` filepath - - """ - return wf().cachefile(name + '.argcache') - - -def _pid_file(name): - """Return path to PID file for ``name``. - - :param name: name of task - :type name: ``unicode`` - :returns: Path to PID file for task - :rtype: ``unicode`` filepath - - """ - return wf().cachefile(name + '.pid') - - -def _process_exists(pid): - """Check if a process with PID ``pid`` exists. - - :param pid: PID to check - :type pid: ``int`` - :returns: ``True`` if process exists, else ``False`` - :rtype: ``Boolean`` - - """ - try: - os.kill(pid, 0) - except OSError: # not running - return False - return True - - -def _job_pid(name): - """Get PID of job or `None` if job does not exist. - - Args: - name (str): Name of job. - - Returns: - int: PID of job process (or `None` if job doesn't exist). - """ - pidfile = _pid_file(name) - if not os.path.exists(pidfile): - return - - with open(pidfile, 'rb') as fp: - pid = int(fp.read()) - - if _process_exists(pid): - return pid - - try: - os.unlink(pidfile) - except Exception: # pragma: no cover - pass - - -def is_running(name): - """Test whether task ``name`` is currently running. - - :param name: name of task - :type name: unicode - :returns: ``True`` if task with name ``name`` is running, else ``False`` - :rtype: bool - - """ - if _job_pid(name) is not None: - return True - - return False - - -def _background(pidfile, stdin='/dev/null', stdout='/dev/null', - stderr='/dev/null'): # pragma: no cover - """Fork the current process into a background daemon. - - :param pidfile: file to write PID of daemon process to. - :type pidfile: filepath - :param stdin: where to read input - :type stdin: filepath - :param stdout: where to write stdout output - :type stdout: filepath - :param stderr: where to write stderr output - :type stderr: filepath - - """ - def _fork_and_exit_parent(errmsg, wait=False, write=False): - try: - pid = os.fork() - if pid > 0: - if write: # write PID of child process to `pidfile` - tmp = pidfile + '.tmp' - with open(tmp, 'wb') as fp: - fp.write(str(pid)) - os.rename(tmp, pidfile) - if wait: # wait for child process to exit - os.waitpid(pid, 0) - os._exit(0) - except OSError as err: - _log().critical('%s: (%d) %s', errmsg, err.errno, err.strerror) - raise err - - # Do first fork and wait for second fork to finish. - _fork_and_exit_parent('fork #1 failed', wait=True) - - # Decouple from parent environment. - os.chdir(wf().workflowdir) - os.setsid() - - # Do second fork and write PID to pidfile. - _fork_and_exit_parent('fork #2 failed', write=True) - - # Now I am a daemon! - # Redirect standard file descriptors. - si = open(stdin, 'r', 0) - so = open(stdout, 'a+', 0) - se = open(stderr, 'a+', 0) - if hasattr(sys.stdin, 'fileno'): - os.dup2(si.fileno(), sys.stdin.fileno()) - if hasattr(sys.stdout, 'fileno'): - os.dup2(so.fileno(), sys.stdout.fileno()) - if hasattr(sys.stderr, 'fileno'): - os.dup2(se.fileno(), sys.stderr.fileno()) - - -def kill(name, sig=signal.SIGTERM): - """Send a signal to job ``name`` via :func:`os.kill`. - - .. versionadded:: 1.29 - - Args: - name (str): Name of the job - sig (int, optional): Signal to send (default: SIGTERM) - - Returns: - bool: `False` if job isn't running, `True` if signal was sent. - """ - pid = _job_pid(name) - if pid is None: - return False - - os.kill(pid, sig) - return True - - -def run_in_background(name, args, **kwargs): - r"""Cache arguments then call this script again via :func:`subprocess.call`. - - :param name: name of job - :type name: unicode - :param args: arguments passed as first argument to :func:`subprocess.call` - :param \**kwargs: keyword arguments to :func:`subprocess.call` - :returns: exit code of sub-process - :rtype: int - - When you call this function, it caches its arguments and then calls - ``background.py`` in a subprocess. The Python subprocess will load the - cached arguments, fork into the background, and then run the command you - specified. - - This function will return as soon as the ``background.py`` subprocess has - forked, returning the exit code of *that* process (i.e. not of the command - you're trying to run). - - If that process fails, an error will be written to the log file. - - If a process is already running under the same name, this function will - return immediately and will not run the specified command. - - """ - if is_running(name): - _log().info('[%s] job already running', name) - return - - argcache = _arg_cache(name) - - # Cache arguments - with open(argcache, 'wb') as fp: - pickle.dump({'args': args, 'kwargs': kwargs}, fp) - _log().debug('[%s] command cached: %s', name, argcache) - - # Call this script - cmd = ['python3', __file__, name] - _log().debug('[%s] passing job to background runner: %r', name, cmd) - retcode = subprocess.call(cmd) - - if retcode: # pragma: no cover - _log().error('[%s] background runner failed with %d', name, retcode) - else: - _log().debug('[%s] background job started', name) - - return retcode - - -def main(wf): # pragma: no cover - """Run command in a background process. - - Load cached arguments, fork into background, then call - :meth:`subprocess.call` with cached arguments. - - """ - log = wf.logger - name = wf.args[0] - argcache = _arg_cache(name) - - - if not os.path.exists(argcache): - msg = '[{0}] command cache not found: {1}'.format(name, argcache) - log.critical(msg) - raise IOError(msg) - - # Fork to background and run command - pidfile = _pid_file(name) - _background(pidfile) - - # Load cached arguments - with open(argcache, 'rb') as fp: - data = pickle.load(fp) - - # Cached arguments - args = data['args'] - kwargs = data['kwargs'] - - # Delete argument cache file - os.unlink(argcache) - - try: - # Run the command - log.debug('[%s] running command: %r', name, args) - - retcode = subprocess.call(args, **kwargs) - - if retcode: - log.error('[%s] command failed with status %d', name, retcode) - finally: - os.unlink(pidfile) - - log.debug('[%s] job complete', name) - - -if __name__ == '__main__': # pragma: no cover - wf().run(main) diff --git a/src/lib/workflow_old/notify.py b/src/lib/workflow_old/notify.py deleted file mode 100644 index a4b7f40..0000000 --- a/src/lib/workflow_old/notify.py +++ /dev/null @@ -1,346 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# -# Copyright (c) 2015 deanishe@deanishe.net -# -# MIT Licence. See http://opensource.org/licenses/MIT -# -# Created on 2015-11-26 -# - -# TODO: Exclude this module from test and code coverage in py2.6 - -""" -Post notifications via the macOS Notification Center. - -This feature is only available on Mountain Lion (10.8) and later. -It will silently fail on older systems. - -The main API is a single function, :func:`~workflow.notify.notify`. - -It works by copying a simple application to your workflow's data -directory. It replaces the application's icon with your workflow's -icon and then calls the application to post notifications. -""" - -from __future__ import print_function, unicode_literals - -import os -import plistlib -import shutil -import subprocess -import sys -import tarfile -import tempfile -import uuid - -import workflow - - -_wf = None -_log = None - - -#: Available system sounds from System Preferences > Sound > Sound Effects -SOUNDS = ( - 'Basso', - 'Blow', - 'Bottle', - 'Frog', - 'Funk', - 'Glass', - 'Hero', - 'Morse', - 'Ping', - 'Pop', - 'Purr', - 'Sosumi', - 'Submarine', - 'Tink', -) - - -def wf(): - """Return Workflow object for this module. - - Returns: - workflow.Workflow: Workflow object for current workflow. - """ - global _wf - if _wf is None: - _wf = workflow.Workflow() - return _wf - - -def log(): - """Return logger for this module. - - Returns: - logging.Logger: Logger for this module. - """ - global _log - if _log is None: - _log = wf().logger - return _log - - -def notifier_program(): - """Return path to notifier applet executable. - - Returns: - unicode: Path to Notify.app ``applet`` executable. - """ - return wf().datafile('Notify.app/Contents/MacOS/applet') - - -def notifier_icon_path(): - """Return path to icon file in installed Notify.app. - - Returns: - unicode: Path to ``applet.icns`` within the app bundle. - """ - return wf().datafile('Notify.app/Contents/Resources/applet.icns') - - -def install_notifier(): - """Extract ``Notify.app`` from the workflow to data directory. - - Changes the bundle ID of the installed app and gives it the - workflow's icon. - """ - archive = os.path.join(os.path.dirname(__file__), 'Notify.tgz') - destdir = wf().datadir - app_path = os.path.join(destdir, 'Notify.app') - n = notifier_program() - log().debug('installing Notify.app to %r ...', destdir) - # z = zipfile.ZipFile(archive, 'r') - # z.extractall(destdir) - tgz = tarfile.open(archive, 'r:gz') - tgz.extractall(destdir) - assert os.path.exists(n), \ - 'Notify.app could not be installed in %s' % destdir - - # Replace applet icon - icon = notifier_icon_path() - workflow_icon = wf().workflowfile('icon.png') - if os.path.exists(icon): - os.unlink(icon) - - png_to_icns(workflow_icon, icon) - - # Set file icon - # PyObjC isn't available for 2.6, so this is 2.7 only. Actually, - # none of this code will "work" on pre-10.8 systems. Let it run - # until I figure out a better way of excluding this module - # from coverage in py2.6. - if sys.version_info >= (2, 7): # pragma: no cover - from AppKit import NSWorkspace, NSImage - - ws = NSWorkspace.sharedWorkspace() - img = NSImage.alloc().init() - img.initWithContentsOfFile_(icon) - ws.setIcon_forFile_options_(img, app_path, 0) - - # Change bundle ID of installed app - ip_path = os.path.join(app_path, 'Contents/Info.plist') - bundle_id = '{0}.{1}'.format(wf().bundleid, uuid.uuid4().hex) - data = plistlib.readPlist(ip_path) - log().debug('changing bundle ID to %r', bundle_id) - data['CFBundleIdentifier'] = bundle_id - plistlib.writePlist(data, ip_path) - - -def validate_sound(sound): - """Coerce ``sound`` to valid sound name. - - Returns ``None`` for invalid sounds. Sound names can be found - in ``System Preferences > Sound > Sound Effects``. - - Args: - sound (str): Name of system sound. - - Returns: - str: Proper name of sound or ``None``. - """ - if not sound: - return None - - # Case-insensitive comparison of `sound` - if sound.lower() in [s.lower() for s in SOUNDS]: - # Title-case is correct for all system sounds as of macOS 10.11 - return sound.title() - return None - - -def notify(title='', text='', sound=None): - """Post notification via Notify.app helper. - - Args: - title (str, optional): Notification title. - text (str, optional): Notification body text. - sound (str, optional): Name of sound to play. - - Raises: - ValueError: Raised if both ``title`` and ``text`` are empty. - - Returns: - bool: ``True`` if notification was posted, else ``False``. - """ - if title == text == '': - raise ValueError('Empty notification') - - sound = validate_sound(sound) or '' - - n = notifier_program() - - if not os.path.exists(n): - install_notifier() - - env = os.environ.copy() - enc = 'utf-8' - env['NOTIFY_TITLE'] = title.encode(enc) - env['NOTIFY_MESSAGE'] = text.encode(enc) - env['NOTIFY_SOUND'] = sound.encode(enc) - cmd = [n] - retcode = subprocess.call(cmd, env=env) - if retcode == 0: - return True - - log().error('Notify.app exited with status {0}.'.format(retcode)) - return False - - -def convert_image(inpath, outpath, size): - """Convert an image file using ``sips``. - - Args: - inpath (str): Path of source file. - outpath (str): Path to destination file. - size (int): Width and height of destination image in pixels. - - Raises: - RuntimeError: Raised if ``sips`` exits with non-zero status. - """ - cmd = [ - b'sips', - b'-z', str(size), str(size), - inpath, - b'--out', outpath] - # log().debug(cmd) - with open(os.devnull, 'w') as pipe: - retcode = subprocess.call(cmd, stdout=pipe, stderr=subprocess.STDOUT) - - if retcode != 0: - raise RuntimeError('sips exited with %d' % retcode) - - -def png_to_icns(png_path, icns_path): - """Convert PNG file to ICNS using ``iconutil``. - - Create an iconset from the source PNG file. Generate PNG files - in each size required by macOS, then call ``iconutil`` to turn - them into a single ICNS file. - - Args: - png_path (str): Path to source PNG file. - icns_path (str): Path to destination ICNS file. - - Raises: - RuntimeError: Raised if ``iconutil`` or ``sips`` fail. - """ - tempdir = tempfile.mkdtemp(prefix='aw-', dir=wf().datadir) - - try: - iconset = os.path.join(tempdir, 'Icon.iconset') - - assert not os.path.exists(iconset), \ - 'iconset already exists: ' + iconset - os.makedirs(iconset) - - # Copy source icon to icon set and generate all the other - # sizes needed - configs = [] - for i in (16, 32, 128, 256, 512): - configs.append(('icon_{0}x{0}.png'.format(i), i)) - configs.append((('icon_{0}x{0}@2x.png'.format(i), i * 2))) - - shutil.copy(png_path, os.path.join(iconset, 'icon_256x256.png')) - shutil.copy(png_path, os.path.join(iconset, 'icon_128x128@2x.png')) - - for name, size in configs: - outpath = os.path.join(iconset, name) - if os.path.exists(outpath): - continue - convert_image(png_path, outpath, size) - - cmd = [ - b'iconutil', - b'-c', b'icns', - b'-o', icns_path, - iconset] - - retcode = subprocess.call(cmd) - if retcode != 0: - raise RuntimeError('iconset exited with %d' % retcode) - - assert os.path.exists(icns_path), \ - 'generated ICNS file not found: ' + repr(icns_path) - finally: - try: - shutil.rmtree(tempdir) - except OSError: # pragma: no cover - pass - - -if __name__ == '__main__': # pragma: nocover - # Simple command-line script to test module with - # This won't work on 2.6, as `argparse` isn't available - # by default. - import argparse - - from unicodedata import normalize - - def ustr(s): - """Coerce `s` to normalised Unicode.""" - return normalize('NFD', s.decode('utf-8')) - - p = argparse.ArgumentParser() - p.add_argument('-p', '--png', help="PNG image to convert to ICNS.") - p.add_argument('-l', '--list-sounds', help="Show available sounds.", - action='store_true') - p.add_argument('-t', '--title', - help="Notification title.", type=ustr, - default='') - p.add_argument('-s', '--sound', type=ustr, - help="Optional notification sound.", default='') - p.add_argument('text', type=ustr, - help="Notification body text.", default='', nargs='?') - o = p.parse_args() - - # List available sounds - if o.list_sounds: - for sound in SOUNDS: - print(sound) - sys.exit(0) - - # Convert PNG to ICNS - if o.png: - icns = os.path.join( - os.path.dirname(o.png), - os.path.splitext(os.path.basename(o.png))[0] + '.icns') - - print('converting {0!r} to {1!r} ...'.format(o.png, icns), - file=sys.stderr) - - assert not os.path.exists(icns), \ - 'destination file already exists: ' + icns - - png_to_icns(o.png, icns) - sys.exit(0) - - # Post notification - if o.title == o.text == '': - print('ERROR: empty notification.', file=sys.stderr) - sys.exit(1) - else: - notify(o.title, o.text, o.sound) diff --git a/src/lib/workflow_old/update.py b/src/lib/workflow_old/update.py deleted file mode 100644 index d4ec5c6..0000000 --- a/src/lib/workflow_old/update.py +++ /dev/null @@ -1,434 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# Copyright (c) 2014 Fabio Niephaus , -# Dean Jackson -# -# MIT Licence. See http://opensource.org/licenses/MIT -# -# Created on 2014-08-16 -# - -"""Self-updating from GitHub. - -.. versionadded:: 1.9 - -.. note:: - - This module is not intended to be used directly. Automatic updates - are controlled by the ``update_settings`` :class:`dict` passed to - :class:`~workflow.workflow.Workflow` objects. - -""" - -from __future__ import print_function, unicode_literals - -import os -import tempfile -import re -import subprocess - -from . import workflow -from . import web - -# __all__ = [] - - -RELEASES_BASE = 'https://api.github.com/repos/{0}/releases' - - -_wf = None - - -def wf(): - """Lazy `Workflow` object.""" - global _wf - if _wf is None: - _wf = workflow.Workflow() - return _wf - - -class Version(object): - """Mostly semantic versioning. - - The main difference to proper :ref:`semantic versioning ` - is that this implementation doesn't require a minor or patch version. - - Version strings may also be prefixed with "v", e.g.: - - >>> v = Version('v1.1.1') - >>> v.tuple - (1, 1, 1, '') - - >>> v = Version('2.0') - >>> v.tuple - (2, 0, 0, '') - - >>> Version('3.1-beta').tuple - (3, 1, 0, 'beta') - - >>> Version('1.0.1') > Version('0.0.1') - True - """ - - #: Match version and pre-release/build information in version strings - match_version = re.compile(r'([0-9\.]+)(.+)?').match - - def __init__(self, vstr): - """Create new `Version` object. - - Args: - vstr (basestring): Semantic version string. - """ - self.vstr = vstr - self.major = 0 - self.minor = 0 - self.patch = 0 - self.suffix = '' - self.build = '' - self._parse(vstr) - - def _parse(self, vstr): - if vstr.startswith('v'): - m = self.match_version(vstr[1:]) - else: - m = self.match_version(vstr) - if not m: - raise ValueError('invalid version number: {0}'.format(vstr)) - - version, suffix = m.groups() - parts = self._parse_dotted_string(version) - self.major = parts.pop(0) - if len(parts): - self.minor = parts.pop(0) - if len(parts): - self.patch = parts.pop(0) - if not len(parts) == 0: - raise ValueError('invalid version (too long) : {0}'.format(vstr)) - - if suffix: - # Build info - idx = suffix.find('+') - if idx > -1: - self.build = suffix[idx+1:] - suffix = suffix[:idx] - if suffix: - if not suffix.startswith('-'): - raise ValueError( - 'suffix must start with - : {0}'.format(suffix)) - self.suffix = suffix[1:] - - # wf().logger.debug('version str `{}` -> {}'.format(vstr, repr(self))) - - def _parse_dotted_string(self, s): - """Parse string ``s`` into list of ints and strings.""" - parsed = [] - parts = s.split('.') - for p in parts: - if p.isdigit(): - p = int(p) - parsed.append(p) - return parsed - - @property - def tuple(self): - """Version number as a tuple of major, minor, patch, pre-release.""" - return (self.major, self.minor, self.patch, self.suffix) - - def __lt__(self, other): - """Implement comparison.""" - if not isinstance(other, Version): - raise ValueError('not a Version instance: {0!r}'.format(other)) - t = self.tuple[:3] - o = other.tuple[:3] - if t < o: - return True - if t == o: # We need to compare suffixes - if self.suffix and not other.suffix: - return True - if other.suffix and not self.suffix: - return False - return (self._parse_dotted_string(self.suffix) < - self._parse_dotted_string(other.suffix)) - # t > o - return False - - def __eq__(self, other): - """Implement comparison.""" - if not isinstance(other, Version): - raise ValueError('not a Version instance: {0!r}'.format(other)) - return self.tuple == other.tuple - - def __ne__(self, other): - """Implement comparison.""" - return not self.__eq__(other) - - def __gt__(self, other): - """Implement comparison.""" - if not isinstance(other, Version): - raise ValueError('not a Version instance: {0!r}'.format(other)) - return other.__lt__(self) - - def __le__(self, other): - """Implement comparison.""" - if not isinstance(other, Version): - raise ValueError('not a Version instance: {0!r}'.format(other)) - return not other.__lt__(self) - - def __ge__(self, other): - """Implement comparison.""" - return not self.__lt__(other) - - def __str__(self): - """Return semantic version string.""" - vstr = '{0}.{1}.{2}'.format(self.major, self.minor, self.patch) - if self.suffix: - vstr = '{0}-{1}'.format(vstr, self.suffix) - if self.build: - vstr = '{0}+{1}'.format(vstr, self.build) - return vstr - - def __repr__(self): - """Return 'code' representation of `Version`.""" - return "Version('{0}')".format(str(self)) - - -def download_workflow(url): - """Download workflow at ``url`` to a local temporary file. - - :param url: URL to .alfredworkflow file in GitHub repo - :returns: path to downloaded file - - """ - filename = url.split('/')[-1] - - if (not filename.endswith('.alfredworkflow') and - not filename.endswith('.alfred3workflow')): - raise ValueError('attachment not a workflow: {0}'.format(filename)) - - local_path = os.path.join(tempfile.gettempdir(), filename) - - wf().logger.debug( - 'downloading updated workflow from `%s` to `%s` ...', url, local_path) - - response = web.get(url) - - with open(local_path, 'wb') as output: - output.write(response.content) - - return local_path - - -def build_api_url(slug): - """Generate releases URL from GitHub slug. - - :param slug: Repo name in form ``username/repo`` - :returns: URL to the API endpoint for the repo's releases - - """ - if len(slug.split('/')) != 2: - raise ValueError('invalid GitHub slug: {0}'.format(slug)) - - return RELEASES_BASE.format(slug) - - -def _validate_release(release): - """Return release for running version of Alfred.""" - alf3 = wf().alfred_version.major == 3 - - downloads = {'.alfredworkflow': [], '.alfred3workflow': []} - dl_count = 0 - version = release['tag_name'] - - for asset in release.get('assets', []): - url = asset.get('browser_download_url') - if not url: # pragma: nocover - continue - - ext = os.path.splitext(url)[1].lower() - if ext not in downloads: - continue - - # Ignore Alfred 3-only files if Alfred 2 is running - if ext == '.alfred3workflow' and not alf3: - continue - - downloads[ext].append(url) - dl_count += 1 - - # download_urls.append(url) - - if dl_count == 0: - wf().logger.warning( - 'invalid release (no workflow file): %s', version) - return None - - for k in downloads: - if len(downloads[k]) > 1: - wf().logger.warning( - 'invalid release (multiple %s files): %s', k, version) - return None - - # Prefer .alfred3workflow file if there is one and Alfred 3 is - # running. - if alf3 and len(downloads['.alfred3workflow']): - download_url = downloads['.alfred3workflow'][0] - - else: - download_url = downloads['.alfredworkflow'][0] - - wf().logger.debug('release %s: %s', version, download_url) - - return { - 'version': version, - 'download_url': download_url, - 'prerelease': release['prerelease'] - } - - -def get_valid_releases(github_slug, prereleases=False): - """Return list of all valid releases. - - :param github_slug: ``username/repo`` for workflow's GitHub repo - :param prereleases: Whether to include pre-releases. - :returns: list of dicts. Each :class:`dict` has the form - ``{'version': '1.1', 'download_url': 'http://github.com/...', - 'prerelease': False }`` - - - A valid release is one that contains one ``.alfredworkflow`` file. - - If the GitHub version (i.e. tag) is of the form ``v1.1``, the leading - ``v`` will be stripped. - - """ - api_url = build_api_url(github_slug) - releases = [] - - wf().logger.debug('retrieving releases list: %s', api_url) - - def retrieve_releases(): - wf().logger.info( - 'retrieving releases: %s', github_slug) - return web.get(api_url).json() - - slug = github_slug.replace('/', '-') - for release in wf().cached_data('gh-releases-' + slug, retrieve_releases): - - release = _validate_release(release) - if release is None: - wf().logger.debug('invalid release: %r', release) - continue - - elif release['prerelease'] and not prereleases: - wf().logger.debug('ignoring prerelease: %s', release['version']) - continue - - wf().logger.debug('release: %r', release) - - releases.append(release) - - return releases - - -def check_update(github_slug, current_version, prereleases=False): - """Check whether a newer release is available on GitHub. - - :param github_slug: ``username/repo`` for workflow's GitHub repo - :param current_version: the currently installed version of the - workflow. :ref:`Semantic versioning ` is required. - :param prereleases: Whether to include pre-releases. - :type current_version: ``unicode`` - :returns: ``True`` if an update is available, else ``False`` - - If an update is available, its version number and download URL will - be cached. - - """ - releases = get_valid_releases(github_slug, prereleases) - - if not len(releases): - wf().logger.warning('no valid releases for %s', github_slug) - wf().cache_data('__workflow_update_status', {'available': False}) - return False - - wf().logger.info('%d releases for %s', len(releases), github_slug) - - # GitHub returns releases newest-first - latest_release = releases[0] - - # (latest_version, download_url) = get_latest_release(releases) - vr = Version(latest_release['version']) - vl = Version(current_version) - wf().logger.debug('latest=%r, installed=%r', vr, vl) - if vr > vl: - - wf().cache_data('__workflow_update_status', { - 'version': latest_release['version'], - 'download_url': latest_release['download_url'], - 'available': True - }) - - return True - - wf().cache_data('__workflow_update_status', {'available': False}) - return False - - -def install_update(): - """If a newer release is available, download and install it. - - :returns: ``True`` if an update is installed, else ``False`` - - """ - update_data = wf().cached_data('__workflow_update_status', max_age=0) - - if not update_data or not update_data.get('available'): - wf().logger.info('no update available') - return False - - local_file = download_workflow(update_data['download_url']) - - wf().logger.info('installing updated workflow ...') - subprocess.call(['open', local_file]) - - update_data['available'] = False - wf().cache_data('__workflow_update_status', update_data) - return True - - -if __name__ == '__main__': # pragma: nocover - import sys - - def show_help(status=0): - """Print help message.""" - print('Usage : update.py (check|install) ' - '[--prereleases] ') - sys.exit(status) - - argv = sys.argv[:] - if '-h' in argv or '--help' in argv: - show_help() - - prereleases = '--prereleases' in argv - - if prereleases: - argv.remove('--prereleases') - - if len(argv) != 4: - show_help(1) - - action, github_slug, version = argv[1:] - - try: - - if action == 'check': - check_update(github_slug, version, prereleases) - elif action == 'install': - install_update() - else: - show_help(1) - - except Exception as err: # ensure traceback is in log file - wf().logger.exception(err) - raise err \ No newline at end of file diff --git a/src/lib/workflow_old/update_old.py b/src/lib/workflow_old/update_old.py deleted file mode 100644 index 6affc94..0000000 --- a/src/lib/workflow_old/update_old.py +++ /dev/null @@ -1,565 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# -# Copyright (c) 2014 Fabio Niephaus , -# Dean Jackson -# -# MIT Licence. See http://opensource.org/licenses/MIT -# -# Created on 2014-08-16 -# - -"""Self-updating from GitHub. - -.. versionadded:: 1.9 - -.. note:: - - This module is not intended to be used directly. Automatic updates - are controlled by the ``update_settings`` :class:`dict` passed to - :class:`~workflow.workflow.Workflow` objects. - -""" - -from __future__ import print_function, unicode_literals - -from collections import defaultdict -from functools import total_ordering -import json -import os -import tempfile -import re -import subprocess - -import workflow -import web - -# __all__ = [] - - -RELEASES_BASE = 'https://api.github.com/repos/{}/releases' -match_workflow = re.compile(r'\.alfred(\d+)?workflow$').search - -_wf = None - - -def wf(): - """Lazy `Workflow` object.""" - global _wf - if _wf is None: - _wf = workflow.Workflow() - return _wf - - -@total_ordering -class Download(object): - """A workflow file that is available for download. - - .. versionadded: 1.37 - - Attributes: - url (str): URL of workflow file. - filename (str): Filename of workflow file. - version (Version): Semantic version of workflow. - prerelease (bool): Whether version is a pre-release. - alfred_version (Version): Minimum compatible version - of Alfred. - - """ - - @classmethod - def from_dict(cls, d): - """Create a `Download` from a `dict`.""" - return cls(url=d['url'], filename=d['filename'], - version=Version(d['version']), - prerelease=d['prerelease']) - - @classmethod - def from_releases(cls, js): - """Extract downloads from GitHub releases. - - Searches releases with semantic tags for assets with - file extension .alfredworkflow or .alfredXworkflow where - X is a number. - - Files are returned sorted by latest version first. Any - releases containing multiple files with the same (workflow) - extension are rejected as ambiguous. - - Args: - js (str): JSON response from GitHub's releases endpoint. - - Returns: - list: Sequence of `Download`. - """ - releases = json.loads(js) - downloads = [] - for release in releases: - tag = release['tag_name'] - dupes = defaultdict(int) - try: - version = Version(tag) - except ValueError as err: - wf().logger.debug('ignored release: bad version "%s": %s', - tag, err) - continue - - dls = [] - for asset in release.get('assets', []): - url = asset.get('browser_download_url') - filename = os.path.basename(url) - m = match_workflow(filename) - if not m: - wf().logger.debug('unwanted file: %s', filename) - continue - - ext = m.group(0) - dupes[ext] = dupes[ext] + 1 - dls.append(Download(url, filename, version, - release['prerelease'])) - - valid = True - for ext, n in dupes.items(): - if n > 1: - wf().logger.debug('ignored release "%s": multiple assets ' - 'with extension "%s"', tag, ext) - valid = False - break - - if valid: - downloads.extend(dls) - - downloads.sort(reverse=True) - return downloads - - def __init__(self, url, filename, version, prerelease=False): - """Create a new Download. - - Args: - url (str): URL of workflow file. - filename (str): Filename of workflow file. - version (Version): Version of workflow. - prerelease (bool, optional): Whether version is - pre-release. Defaults to False. - - """ - if isinstance(version, basestring): - version = Version(version) - - self.url = url - self.filename = filename - self.version = version - self.prerelease = prerelease - - @property - def alfred_version(self): - """Minimum Alfred version based on filename extension.""" - m = match_workflow(self.filename) - if not m or not m.group(1): - return Version('0') - return Version(m.group(1)) - - @property - def dict(self): - """Convert `Download` to `dict`.""" - return dict(url=self.url, filename=self.filename, - version=str(self.version), prerelease=self.prerelease) - - def __str__(self): - """Format `Download` for printing.""" - u = ('Download(url={dl.url!r}, ' - 'filename={dl.filename!r}, ' - 'version={dl.version!r}, ' - 'prerelease={dl.prerelease!r})'.format(dl=self)) - - return u.encode('utf-8') - - def __repr__(self): - """Code-like representation of `Download`.""" - return str(self) - - def __eq__(self, other): - """Compare Downloads based on version numbers.""" - if self.url != other.url \ - or self.filename != other.filename \ - or self.version != other.version \ - or self.prerelease != other.prerelease: - return False - return True - - def __ne__(self, other): - """Compare Downloads based on version numbers.""" - return not self.__eq__(other) - - def __lt__(self, other): - """Compare Downloads based on version numbers.""" - if self.version != other.version: - return self.version < other.version - return self.alfred_version < other.alfred_version - - -class Version(object): - """Mostly semantic versioning. - - The main difference to proper :ref:`semantic versioning ` - is that this implementation doesn't require a minor or patch version. - - Version strings may also be prefixed with "v", e.g.: - - >>> v = Version('v1.1.1') - >>> v.tuple - (1, 1, 1, '') - - >>> v = Version('2.0') - >>> v.tuple - (2, 0, 0, '') - - >>> Version('3.1-beta').tuple - (3, 1, 0, 'beta') - - >>> Version('1.0.1') > Version('0.0.1') - True - """ - - #: Match version and pre-release/build information in version strings - match_version = re.compile(r'([0-9][0-9\.]*)(.+)?').match - - def __init__(self, vstr): - """Create new `Version` object. - - Args: - vstr (basestring): Semantic version string. - """ - if not vstr: - raise ValueError('invalid version number: {!r}'.format(vstr)) - - self.vstr = vstr - self.major = 0 - self.minor = 0 - self.patch = 0 - self.suffix = '' - self.build = '' - self._parse(vstr) - - def _parse(self, vstr): - if vstr.startswith('v'): - m = self.match_version(vstr[1:]) - else: - m = self.match_version(vstr) - if not m: - raise ValueError('invalid version number: ' + vstr) - - version, suffix = m.groups() - parts = self._parse_dotted_string(version) - self.major = parts.pop(0) - if len(parts): - self.minor = parts.pop(0) - if len(parts): - self.patch = parts.pop(0) - if not len(parts) == 0: - raise ValueError('version number too long: ' + vstr) - - if suffix: - # Build info - idx = suffix.find('+') - if idx > -1: - self.build = suffix[idx+1:] - suffix = suffix[:idx] - if suffix: - if not suffix.startswith('-'): - raise ValueError( - 'suffix must start with - : ' + suffix) - self.suffix = suffix[1:] - - def _parse_dotted_string(self, s): - """Parse string ``s`` into list of ints and strings.""" - parsed = [] - parts = s.split('.') - for p in parts: - if p.isdigit(): - p = int(p) - parsed.append(p) - return parsed - - @property - def tuple(self): - """Version number as a tuple of major, minor, patch, pre-release.""" - return (self.major, self.minor, self.patch, self.suffix) - - def __lt__(self, other): - """Implement comparison.""" - if not isinstance(other, Version): - raise ValueError('not a Version instance: {0!r}'.format(other)) - t = self.tuple[:3] - o = other.tuple[:3] - if t < o: - return True - if t == o: # We need to compare suffixes - if self.suffix and not other.suffix: - return True - if other.suffix and not self.suffix: - return False - return self._parse_dotted_string(self.suffix) \ - < self._parse_dotted_string(other.suffix) - # t > o - return False - - def __eq__(self, other): - """Implement comparison.""" - if not isinstance(other, Version): - raise ValueError('not a Version instance: {0!r}'.format(other)) - return self.tuple == other.tuple - - def __ne__(self, other): - """Implement comparison.""" - return not self.__eq__(other) - - def __gt__(self, other): - """Implement comparison.""" - if not isinstance(other, Version): - raise ValueError('not a Version instance: {0!r}'.format(other)) - return other.__lt__(self) - - def __le__(self, other): - """Implement comparison.""" - if not isinstance(other, Version): - raise ValueError('not a Version instance: {0!r}'.format(other)) - return not other.__lt__(self) - - def __ge__(self, other): - """Implement comparison.""" - return not self.__lt__(other) - - def __str__(self): - """Return semantic version string.""" - vstr = '{0}.{1}.{2}'.format(self.major, self.minor, self.patch) - if self.suffix: - vstr = '{0}-{1}'.format(vstr, self.suffix) - if self.build: - vstr = '{0}+{1}'.format(vstr, self.build) - return vstr - - def __repr__(self): - """Return 'code' representation of `Version`.""" - return "Version('{0}')".format(str(self)) - - -def retrieve_download(dl): - """Saves a download to a temporary file and returns path. - - .. versionadded: 1.37 - - Args: - url (unicode): URL to .alfredworkflow file in GitHub repo - - Returns: - unicode: path to downloaded file - - """ - if not match_workflow(dl.filename): - raise ValueError('attachment not a workflow: ' + dl.filename) - - path = os.path.join(tempfile.gettempdir(), dl.filename) - wf().logger.debug('downloading update from ' - '%r to %r ...', dl.url, path) - - r = web.get(dl.url) - r.raise_for_status() - - r.save_to_path(path) - - return path - - -def build_api_url(repo): - """Generate releases URL from GitHub repo. - - Args: - repo (unicode): Repo name in form ``username/repo`` - - Returns: - unicode: URL to the API endpoint for the repo's releases - - """ - if len(repo.split('/')) != 2: - raise ValueError('invalid GitHub repo: {!r}'.format(repo)) - - return RELEASES_BASE.format(repo) - - -def get_downloads(repo): - """Load available ``Download``s for GitHub repo. - - .. versionadded: 1.37 - - Args: - repo (unicode): GitHub repo to load releases for. - - Returns: - list: Sequence of `Download` contained in GitHub releases. - """ - url = build_api_url(repo) - - def _fetch(): - wf().logger.info('retrieving releases for %r ...', repo) - r = web.get(url) - r.raise_for_status() - return r.content - - key = 'github-releases-' + repo.replace('/', '-') - js = wf().cached_data(key, _fetch, max_age=60) - - return Download.from_releases(js) - - -def latest_download(dls, alfred_version=None, prereleases=False): - """Return newest `Download`.""" - alfred_version = alfred_version or os.getenv('alfred_version') - version = None - if alfred_version: - version = Version(alfred_version) - - dls.sort(reverse=True) - for dl in dls: - if dl.prerelease and not prereleases: - wf().logger.debug('ignored prerelease: %s', dl.version) - continue - if version and dl.alfred_version > version: - wf().logger.debug('ignored incompatible (%s > %s): %s', - dl.alfred_version, version, dl.filename) - continue - - wf().logger.debug('latest version: %s (%s)', dl.version, dl.filename) - return dl - - return None - - -def check_update(repo, current_version, prereleases=False, - alfred_version=None): - """Check whether a newer release is available on GitHub. - - Args: - repo (unicode): ``username/repo`` for workflow's GitHub repo - current_version (unicode): the currently installed version of the - workflow. :ref:`Semantic versioning ` is required. - prereleases (bool): Whether to include pre-releases. - alfred_version (unicode): version of currently-running Alfred. - if empty, defaults to ``$alfred_version`` environment variable. - - Returns: - bool: ``True`` if an update is available, else ``False`` - - If an update is available, its version number and download URL will - be cached. - - """ - key = '__workflow_latest_version' - # data stored when no update is available - no_update = { - 'available': False, - 'download': None, - 'version': None, - } - current = Version(current_version) - - dls = get_downloads(repo) - if not len(dls): - wf().logger.warning('no valid downloads for %s', repo) - wf().cache_data(key, no_update) - return False - - wf().logger.info('%d download(s) for %s', len(dls), repo) - - dl = latest_download(dls, alfred_version, prereleases) - - if not dl: - wf().logger.warning('no compatible downloads for %s', repo) - wf().cache_data(key, no_update) - return False - - wf().logger.debug('latest=%r, installed=%r', dl.version, current) - - if dl.version > current: - wf().cache_data(key, { - 'version': str(dl.version), - 'download': dl.dict, - 'available': True, - }) - return True - - wf().cache_data(key, no_update) - return False - - -def install_update(): - """If a newer release is available, download and install it. - - :returns: ``True`` if an update is installed, else ``False`` - - """ - key = '__workflow_latest_version' - # data stored when no update is available - no_update = { - 'available': False, - 'download': None, - 'version': None, - } - status = wf().cached_data(key, max_age=0) - - if not status or not status.get('available'): - wf().logger.info('no update available') - return False - - dl = status.get('download') - if not dl: - wf().logger.info('no download information') - return False - - path = retrieve_download(Download.from_dict(dl)) - - wf().logger.info('installing updated workflow ...') - subprocess.call(['open', path]) - - wf().cache_data(key, no_update) - return True - - -if __name__ == '__main__': # pragma: nocover - import sys - - prereleases = False - - def show_help(status=0): - """Print help message.""" - print('usage: update.py (check|install) ' - '[--prereleases] ') - sys.exit(status) - - argv = sys.argv[:] - if '-h' in argv or '--help' in argv: - show_help() - - if '--prereleases' in argv: - argv.remove('--prereleases') - prereleases = True - - if len(argv) != 4: - show_help(1) - - action = argv[1] - repo = argv[2] - version = argv[3] - - try: - - if action == 'check': - check_update(repo, version, prereleases) - elif action == 'install': - install_update() - else: - show_help(1) - - except Exception as err: # ensure traceback is in log file - wf().logger.exception(err) - raise err diff --git a/src/lib/workflow_old/util.py b/src/lib/workflow_old/util.py deleted file mode 100644 index 0b994ea..0000000 --- a/src/lib/workflow_old/util.py +++ /dev/null @@ -1,552 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# Copyright (c) 2017 Dean Jackson -# -# MIT Licence. See http://opensource.org/licenses/MIT -# -# Created on 2017-12-17 -# - -"""A selection of helper functions useful for building workflows.""" - -from __future__ import print_function, absolute_import - -import atexit -from collections import namedtuple -from contextlib import contextmanager -import errno -import fcntl -import functools -import json -import os -import signal -import subprocess -import sys -from threading import Event -import time - -# JXA scripts to call Alfred's API via the Scripting Bridge -# {app} is automatically replaced with "Alfred 3" or -# "com.runningwithcrayons.Alfred" depending on version. -# -# Open Alfred in search (regular) mode -JXA_SEARCH = "Application({app}).search({arg});" -# Open Alfred's File Actions on an argument -JXA_ACTION = "Application({app}).action({arg});" -# Open Alfred's navigation mode at path -JXA_BROWSE = "Application({app}).browse({arg});" -# Set the specified theme -JXA_SET_THEME = "Application({app}).setTheme({arg});" -# Call an External Trigger -JXA_TRIGGER = "Application({app}).runTrigger({arg}, {opts});" -# Save a variable to the workflow configuration sheet/info.plist -JXA_SET_CONFIG = "Application({app}).setConfiguration({arg}, {opts});" -# Delete a variable from the workflow configuration sheet/info.plist -JXA_UNSET_CONFIG = "Application({app}).removeConfiguration({arg}, {opts});" - - -class AcquisitionError(Exception): - """Raised if a lock cannot be acquired.""" - - -AppInfo = namedtuple('AppInfo', ['name', 'path', 'bundleid']) -"""Information about an installed application. - -Returned by :func:`appinfo`. All attributes are Unicode. - -.. py:attribute:: name - - Name of the application, e.g. ``u'Safari'``. - -.. py:attribute:: path - - Path to the application bundle, e.g. ``u'/Applications/Safari.app'``. - -.. py:attribute:: bundleid - - Application's bundle ID, e.g. ``u'com.apple.Safari'``. - -""" - - -def jxa_app_name(): - """Return name of application to call currently running Alfred. - - .. versionadded: 1.37 - - Returns 'Alfred 3' or 'com.runningwithcrayons.Alfred' depending - on which version of Alfred is running. - - This name is suitable for use with ``Application(name)`` in JXA. - - Returns: - unicode: Application name or ID. - - """ - if os.getenv('alfred_version', '').startswith('3'): - # Alfred 3 - return u'Alfred 3' - # Alfred 4+ - return u'com.runningwithcrayons.Alfred' - - -def unicodify(s, encoding='utf-8', norm=None): - """Ensure string is Unicode. - - .. versionadded:: 1.31 - - Decode encoded strings using ``encoding`` and normalise Unicode - to form ``norm`` if specified. - - Args: - s (str): String to decode. May also be Unicode. - encoding (str, optional): Encoding to use on bytestrings. - norm (None, optional): Normalisation form to apply to Unicode string. - - Returns: - unicode: Decoded, optionally normalised, Unicode string. - - """ - if not isinstance(s, unicode): - s = unicode(s, encoding) - - if norm: - from unicodedata import normalize - s = normalize(norm, s) - - return s - - -def utf8ify(s): - """Ensure string is a bytestring. - - .. versionadded:: 1.31 - - Returns `str` objects unchanced, encodes `unicode` objects to - UTF-8, and calls :func:`str` on anything else. - - Args: - s (object): A Python object - - Returns: - str: UTF-8 string or string representation of s. - - """ - if isinstance(s, str): - return s - - if isinstance(s, unicode): - return s.encode('utf-8') - - return str(s) - - -def applescriptify(s): - """Escape string for insertion into an AppleScript string. - - .. versionadded:: 1.31 - - Replaces ``"`` with `"& quote &"`. Use this function if you want - - to insert a string into an AppleScript script: - >>> query = 'g "python" test' - >>> applescriptify(query) - 'g " & quote & "python" & quote & "test' - - Args: - s (unicode): Unicode string to escape. - - Returns: - unicode: Escaped string - - """ - return s.replace(u'"', u'" & quote & "') - - -def run_command(cmd, **kwargs): - """Run a command and return the output. - - .. versionadded:: 1.31 - - A thin wrapper around :func:`subprocess.check_output` that ensures - all arguments are encoded to UTF-8 first. - - Args: - cmd (list): Command arguments to pass to ``check_output``. - **kwargs: Keyword arguments to pass to ``check_output``. - - Returns: - str: Output returned by ``check_output``. - - """ - cmd = [utf8ify(s) for s in cmd] - return subprocess.check_output(cmd, **kwargs) - - -def run_applescript(script, *args, **kwargs): - """Execute an AppleScript script and return its output. - - .. versionadded:: 1.31 - - Run AppleScript either by filepath or code. If ``script`` is a valid - filepath, that script will be run, otherwise ``script`` is treated - as code. - - Args: - script (str, optional): Filepath of script or code to run. - *args: Optional command-line arguments to pass to the script. - **kwargs: Pass ``lang`` to run a language other than AppleScript. - - Returns: - str: Output of run command. - - """ - lang = 'AppleScript' - if 'lang' in kwargs: - lang = kwargs['lang'] - del kwargs['lang'] - - cmd = ['/usr/bin/osascript', '-l', lang] - - if os.path.exists(script): - cmd += [script] - else: - cmd += ['-e', script] - - cmd.extend(args) - - return run_command(cmd, **kwargs) - - -def run_jxa(script, *args): - """Execute a JXA script and return its output. - - .. versionadded:: 1.31 - - Wrapper around :func:`run_applescript` that passes ``lang=JavaScript``. - - Args: - script (str): Filepath of script or code to run. - *args: Optional command-line arguments to pass to script. - - Returns: - str: Output of script. - - """ - return run_applescript(script, *args, lang='JavaScript') - - -def run_trigger(name, bundleid=None, arg=None): - """Call an Alfred External Trigger. - - .. versionadded:: 1.31 - - If ``bundleid`` is not specified, reads the bundle ID of the current - workflow from Alfred's environment variables. - - Args: - name (str): Name of External Trigger to call. - bundleid (str, optional): Bundle ID of workflow trigger belongs to. - arg (str, optional): Argument to pass to trigger. - - """ - bundleid = bundleid or os.getenv('alfred_workflow_bundleid') - appname = jxa_app_name() - opts = {'inWorkflow': bundleid} - if arg: - opts['withArgument'] = arg - - script = JXA_TRIGGER.format(app=json.dumps(appname), - arg=json.dumps(name), - opts=json.dumps(opts, sort_keys=True)) - - run_applescript(script, lang='JavaScript') - - -def set_config(name, value, bundleid=None, exportable=False): - """Set a workflow variable in ``info.plist``. - - .. versionadded:: 1.33 - - Args: - name (str): Name of variable to set. - value (str): Value to set variable to. - bundleid (str, optional): Bundle ID of workflow variable belongs to. - exportable (bool, optional): Whether variable should be marked - as exportable (Don't Export checkbox). - - """ - bundleid = bundleid or os.getenv('alfred_workflow_bundleid') - appname = jxa_app_name() - opts = { - 'toValue': value, - 'inWorkflow': bundleid, - 'exportable': exportable, - } - - script = JXA_SET_CONFIG.format(app=json.dumps(appname), - arg=json.dumps(name), - opts=json.dumps(opts, sort_keys=True)) - - run_applescript(script, lang='JavaScript') - - -def unset_config(name, bundleid=None): - """Delete a workflow variable from ``info.plist``. - - .. versionadded:: 1.33 - - Args: - name (str): Name of variable to delete. - bundleid (str, optional): Bundle ID of workflow variable belongs to. - - """ - bundleid = bundleid or os.getenv('alfred_workflow_bundleid') - appname = jxa_app_name() - opts = {'inWorkflow': bundleid} - - script = JXA_UNSET_CONFIG.format(app=json.dumps(appname), - arg=json.dumps(name), - opts=json.dumps(opts, sort_keys=True)) - - run_applescript(script, lang='JavaScript') - - -def appinfo(name): - """Get information about an installed application. - - .. versionadded:: 1.31 - - Args: - name (str): Name of application to look up. - - Returns: - AppInfo: :class:`AppInfo` tuple or ``None`` if app isn't found. - - """ - cmd = ['mdfind', '-onlyin', '/Applications', - '-onlyin', os.path.expanduser('~/Applications'), - '(kMDItemContentTypeTree == com.apple.application &&' - '(kMDItemDisplayName == "{0}" || kMDItemFSName == "{0}.app"))' - .format(name)] - - output = run_command(cmd).strip() - if not output: - return None - - path = output.split('\n')[0] - - cmd = ['mdls', '-raw', '-name', 'kMDItemCFBundleIdentifier', path] - bid = run_command(cmd).strip() - if not bid: # pragma: no cover - return None - - return AppInfo(unicodify(name), unicodify(path), unicodify(bid)) - - -@contextmanager -def atomic_writer(fpath, mode): - """Atomic file writer. - - .. versionadded:: 1.12 - - Context manager that ensures the file is only written if the write - succeeds. The data is first written to a temporary file. - - :param fpath: path of file to write to. - :type fpath: ``unicode`` - :param mode: sames as for :func:`open` - :type mode: string - - """ - suffix = '.{}.tmp'.format(os.getpid()) - temppath = fpath + suffix - with open(temppath, mode) as fp: - try: - yield fp - os.rename(temppath, fpath) - finally: - try: - os.remove(temppath) - except (OSError, IOError): - pass - - -class LockFile(object): - """Context manager to protect filepaths with lockfiles. - - .. versionadded:: 1.13 - - Creates a lockfile alongside ``protected_path``. Other ``LockFile`` - instances will refuse to lock the same path. - - >>> path = '/path/to/file' - >>> with LockFile(path): - >>> with open(path, 'wb') as fp: - >>> fp.write(data) - - Args: - protected_path (unicode): File to protect with a lockfile - timeout (float, optional): Raises an :class:`AcquisitionError` - if lock cannot be acquired within this number of seconds. - If ``timeout`` is 0 (the default), wait forever. - delay (float, optional): How often to check (in seconds) if - lock has been released. - - Attributes: - delay (float): How often to check (in seconds) whether the lock - can be acquired. - lockfile (unicode): Path of the lockfile. - timeout (float): How long to wait to acquire the lock. - - """ - - def __init__(self, protected_path, timeout=0.0, delay=0.05): - """Create new :class:`LockFile` object.""" - self.lockfile = protected_path + '.lock' - self._lockfile = None - self.timeout = timeout - self.delay = delay - self._lock = Event() - atexit.register(self.release) - - @property - def locked(self): - """``True`` if file is locked by this instance.""" - return self._lock.is_set() - - def acquire(self, blocking=True): - """Acquire the lock if possible. - - If the lock is in use and ``blocking`` is ``False``, return - ``False``. - - Otherwise, check every :attr:`delay` seconds until it acquires - lock or exceeds attr:`timeout` and raises an :class:`AcquisitionError`. - - """ - if self.locked and not blocking: - return False - - start = time.time() - while True: - # Raise error if we've been waiting too long to acquire the lock - if self.timeout and (time.time() - start) >= self.timeout: - raise AcquisitionError('lock acquisition timed out') - - # If already locked, wait then try again - if self.locked: - time.sleep(self.delay) - continue - - # Create in append mode so we don't lose any contents - if self._lockfile is None: - self._lockfile = open(self.lockfile, 'a') - - # Try to acquire the lock - try: - fcntl.lockf(self._lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB) - self._lock.set() - break - except IOError as err: # pragma: no cover - if err.errno not in (errno.EACCES, errno.EAGAIN): - raise - - # Don't try again - if not blocking: # pragma: no cover - return False - - # Wait, then try again - time.sleep(self.delay) - - return True - - def release(self): - """Release the lock by deleting `self.lockfile`.""" - if not self._lock.is_set(): - return False - - try: - fcntl.lockf(self._lockfile, fcntl.LOCK_UN) - except IOError: # pragma: no cover - pass - finally: - self._lock.clear() - self._lockfile = None - try: - os.unlink(self.lockfile) - except (IOError, OSError): # pragma: no cover - pass - - return True - - def __enter__(self): - """Acquire lock.""" - self.acquire() - return self - - def __exit__(self, typ, value, traceback): - """Release lock.""" - self.release() - - def __del__(self): - """Clear up `self.lockfile`.""" - self.release() # pragma: no cover - - -class uninterruptible(object): - """Decorator that postpones SIGTERM until wrapped function returns. - - .. versionadded:: 1.12 - - .. important:: This decorator is NOT thread-safe. - - As of version 2.7, Alfred allows Script Filters to be killed. If - your workflow is killed in the middle of critical code (e.g. - writing data to disk), this may corrupt your workflow's data. - - Use this decorator to wrap critical functions that *must* complete. - If the script is killed while a wrapped function is executing, - the SIGTERM will be caught and handled after your function has - finished executing. - - Alfred-Workflow uses this internally to ensure its settings, data - and cache writes complete. - - """ - - def __init__(self, func, class_name=''): - """Decorate `func`.""" - self.func = func - functools.update_wrapper(self, func) - self._caught_signal = None - - def signal_handler(self, signum, frame): - """Called when process receives SIGTERM.""" - self._caught_signal = (signum, frame) - - def __call__(self, *args, **kwargs): - """Trap ``SIGTERM`` and call wrapped function.""" - self._caught_signal = None - # Register handler for SIGTERM, then call `self.func` - self.old_signal_handler = signal.getsignal(signal.SIGTERM) - signal.signal(signal.SIGTERM, self.signal_handler) - - self.func(*args, **kwargs) - - # Restore old signal handler - signal.signal(signal.SIGTERM, self.old_signal_handler) - - # Handle any signal caught during execution - if self._caught_signal is not None: - signum, frame = self._caught_signal - if callable(self.old_signal_handler): - self.old_signal_handler(signum, frame) - elif self.old_signal_handler == signal.SIG_DFL: - sys.exit(0) - - def __get__(self, obj=None, klass=None): - """Decorator API.""" - return self.__class__(self.func.__get__(obj, klass), - klass.__name__) diff --git a/src/lib/workflow_old/version b/src/lib/workflow_old/version deleted file mode 100644 index 673b6a6..0000000 --- a/src/lib/workflow_old/version +++ /dev/null @@ -1 +0,0 @@ -1.37.2 \ No newline at end of file diff --git a/src/lib/workflow_old/web.py b/src/lib/workflow_old/web.py deleted file mode 100644 index 96a59e9..0000000 --- a/src/lib/workflow_old/web.py +++ /dev/null @@ -1,677 +0,0 @@ -# encoding: utf-8 -# -# Copyright (c) 2014 Dean Jackson -# -# MIT Licence. See http://opensource.org/licenses/MIT -# -# Created on 2014-02-15 -# - -"""Lightweight HTTP library with a requests-like interface.""" - -import codecs -import json -import mimetypes -import os -import random -import re -import socket -import string -import unicodedata -import urllib.request -import urllib.parse -import zlib - - -USER_AGENT = u'Alfred-Workflow/1.19 (+http://www.deanishe.net/alfred-workflow)' - -# Valid characters for multipart form data boundaries -BOUNDARY_CHARS = string.digits + string.ascii_letters - -# HTTP response codes -RESPONSES = { - 100: 'Continue', - 101: 'Switching Protocols', - 200: 'OK', - 201: 'Created', - 202: 'Accepted', - 203: 'Non-Authoritative Information', - 204: 'No Content', - 205: 'Reset Content', - 206: 'Partial Content', - 300: 'Multiple Choices', - 301: 'Moved Permanently', - 302: 'Found', - 303: 'See Other', - 304: 'Not Modified', - 305: 'Use Proxy', - 307: 'Temporary Redirect', - 400: 'Bad Request', - 401: 'Unauthorized', - 402: 'Payment Required', - 403: 'Forbidden', - 404: 'Not Found', - 405: 'Method Not Allowed', - 406: 'Not Acceptable', - 407: 'Proxy Authentication Required', - 408: 'Request Timeout', - 409: 'Conflict', - 410: 'Gone', - 411: 'Length Required', - 412: 'Precondition Failed', - 413: 'Request Entity Too Large', - 414: 'Request-URI Too Long', - 415: 'Unsupported Media Type', - 416: 'Requested Range Not Satisfiable', - 417: 'Expectation Failed', - 500: 'Internal Server Error', - 501: 'Not Implemented', - 502: 'Bad Gateway', - 503: 'Service Unavailable', - 504: 'Gateway Timeout', - 505: 'HTTP Version Not Supported' -} - - -def str_dict(dic): - """Convert keys and values in ``dic`` into UTF-8-encoded :class:`str`. - - :param dic: Mapping of Unicode strings - :type dic: dict - :returns: Dictionary containing only UTF-8 strings - :rtype: dict - - """ - if isinstance(dic, CaseInsensitiveDictionary): - dic2 = CaseInsensitiveDictionary() - else: - dic2 = {} - for k, v in dic.items(): - if isinstance(k, unicode): - k = k.encode('utf-8') - if isinstance(v, unicode): - v = v.encode('utf-8') - dic2[k] = v - return dic2 - - -class NoRedirectHandler(urllib.request.HTTPRedirectHandler): - """Prevent redirections.""" - - def redirect_request(self, *args): - return None - - -# Adapted from https://gist.github.com/babakness/3901174 -class CaseInsensitiveDictionary(dict): - """Dictionary with caseless key search. - - Enables case insensitive searching while preserving case sensitivity - when keys are listed, ie, via keys() or items() methods. - - Works by storing a lowercase version of the key as the new key and - stores the original key-value pair as the key's value - (values become dictionaries). - - """ - - def __init__(self, initval=None): - """Create new case-insensitive dictionary.""" - if isinstance(initval, dict): - for key, value in initval.iteritems(): - self.__setitem__(key, value) - - elif isinstance(initval, list): - for (key, value) in initval: - self.__setitem__(key, value) - - def __contains__(self, key): - return dict.__contains__(self, key.lower()) - - def __getitem__(self, key): - return dict.__getitem__(self, key.lower())['val'] - - def __setitem__(self, key, value): - return dict.__setitem__(self, key.lower(), {'key': key, 'val': value}) - - def get(self, key, default=None): - try: - v = dict.__getitem__(self, key.lower()) - except KeyError: - return default - else: - return v['val'] - - def update(self, other): - for k, v in other.items(): - self[k] = v - - def items(self): - return [(v['key'], v['val']) for v in dict.itervalues(self)] - - def keys(self): - return [v['key'] for v in dict.itervalues(self)] - - def values(self): - return [v['val'] for v in dict.itervalues(self)] - - def iteritems(self): - for v in dict.itervalues(self): - yield v['key'], v['val'] - - def iterkeys(self): - for v in dict.itervalues(self): - yield v['key'] - - def itervalues(self): - for v in dict.itervalues(self): - yield v['val'] - - -class Response(object): - """ - Returned by :func:`request` / :func:`get` / :func:`post` functions. - - Simplified version of the ``Response`` object in the ``requests`` library. - - >>> r = request('http://www.google.com') - >>> r.status_code - 200 - >>> r.encoding - ISO-8859-1 - >>> r.content # bytes - ... - >>> r.text # unicode, decoded according to charset in HTTP header/meta tag - u' ...' - >>> r.json() # content parsed as JSON - - """ - - def __init__(self, request, stream=False): - """Call `request` with :mod:`urllib2` and process results. - - :param request: :class:`urllib2.Request` instance - :param stream: Whether to stream response or retrieve it all at once - :type stream: bool - - """ - self.request = request - self._stream = stream - self.url = None - self.raw = None - self._encoding = None - self.error = None - self.status_code = None - self.reason = None - self.headers = CaseInsensitiveDictionary() - self._content = None - self._content_loaded = False - self._gzipped = False - - # Execute query - try: - self.raw = urllib.request.urlopen(request) - except urllib.request.HTTPError as err: - self.error = err - try: - self.url = err.geturl() - # sometimes (e.g. when authentication fails) - # urllib can't get a URL from an HTTPError - # This behaviour changes across Python versions, - # so no test cover (it isn't important). - except AttributeError: # pragma: no cover - pass - self.status_code = err.code - else: - self.status_code = self.raw.getcode() - self.url = self.raw.geturl() - self.reason = RESPONSES.get(self.status_code) - - # Parse additional info if request succeeded - if not self.error: - headers = self.raw.info() - self.transfer_encoding = headers.getencoding() - self.mimetype = headers.gettype() - for key in headers.keys(): - self.headers[key.lower()] = headers.get(key) - - # Is content gzipped? - # Transfer-Encoding appears to not be used in the wild - # (contrary to the HTTP standard), but no harm in testing - # for it - if ('gzip' in headers.get('content-encoding', '') or - 'gzip' in headers.get('transfer-encoding', '')): - self._gzipped = True - - @property - def stream(self): - """Whether response is streamed. - - Returns: - bool: `True` if response is streamed. - """ - return self._stream - - @stream.setter - def stream(self, value): - if self._content_loaded: - raise RuntimeError("`content` has already been read from " - "this Response.") - - self._stream = value - - def json(self): - """Decode response contents as JSON. - - :returns: object decoded from JSON - :rtype: list, dict or unicode - - """ - return json.loads(self.content, self.encoding or 'utf-8') - - @property - def encoding(self): - """Text encoding of document or ``None``. - - :returns: Text encoding if found. - :rtype: str or ``None`` - - """ - if not self._encoding: - self._encoding = self._get_encoding() - - return self._encoding - - @property - def content(self): - """Raw content of response (i.e. bytes). - - :returns: Body of HTTP response - :rtype: str - - """ - if not self._content: - - # Decompress gzipped content - if self._gzipped: - decoder = zlib.decompressobj(16 + zlib.MAX_WBITS) - self._content = decoder.decompress(self.raw.read()) - - else: - self._content = self.raw.read() - - self._content_loaded = True - - return self._content - - @property - def text(self): - """Unicode-decoded content of response body. - - If no encoding can be determined from HTTP headers or the content - itself, the encoded response body will be returned instead. - - :returns: Body of HTTP response - :rtype: unicode or str - - """ - if self.encoding: - return unicodedata.normalize('NFC', unicode(self.content, - self.encoding)) - return self.content - - def iter_content(self, chunk_size=4096, decode_unicode=False): - """Iterate over response data. - - .. versionadded:: 1.6 - - :param chunk_size: Number of bytes to read into memory - :type chunk_size: int - :param decode_unicode: Decode to Unicode using detected encoding - :type decode_unicode: bool - :returns: iterator - - """ - if not self.stream: - raise RuntimeError("You cannot call `iter_content` on a " - "Response unless you passed `stream=True`" - " to `get()`/`post()`/`request()`.") - - if self._content_loaded: - raise RuntimeError( - "`content` has already been read from this Response.") - - def decode_stream(iterator, r): - - decoder = codecs.getincrementaldecoder(r.encoding)(errors='replace') - - for chunk in iterator: - data = decoder.decode(chunk) - if data: - yield data - - data = decoder.decode(b'', final=True) - if data: # pragma: no cover - yield data - - def generate(): - - if self._gzipped: - decoder = zlib.decompressobj(16 + zlib.MAX_WBITS) - - while True: - chunk = self.raw.read(chunk_size) - if not chunk: - break - - if self._gzipped: - chunk = decoder.decompress(chunk) - - yield chunk - - chunks = generate() - - if decode_unicode and self.encoding: - chunks = decode_stream(chunks, self) - - return chunks - - def save_to_path(self, filepath): - """Save retrieved data to file at ``filepath``. - - .. versionadded: 1.9.6 - - :param filepath: Path to save retrieved data. - - """ - filepath = os.path.abspath(filepath) - dirname = os.path.dirname(filepath) - if not os.path.exists(dirname): - os.makedirs(dirname) - - self.stream = True - - with open(filepath, 'wb') as fileobj: - for data in self.iter_content(): - fileobj.write(data) - - def raise_for_status(self): - """Raise stored error if one occurred. - - error will be instance of :class:`urllib2.HTTPError` - """ - if self.error is not None: - raise self.error - return - - def _get_encoding(self): - """Get encoding from HTTP headers or content. - - :returns: encoding or `None` - :rtype: unicode or ``None`` - - """ - headers = self.raw.info() - encoding = None - - if headers.getparam('charset'): - encoding = headers.getparam('charset') - - # HTTP Content-Type header - for param in headers.getplist(): - if param.startswith('charset='): - encoding = param[8:] - break - - if not self.stream: # Try sniffing response content - # Encoding declared in document should override HTTP headers - if self.mimetype == 'text/html': # sniff HTML headers - m = re.search("""""", - self.content) - if m: - encoding = m.group(1) - - elif ((self.mimetype.startswith('application/') or - self.mimetype.startswith('text/')) and - 'xml' in self.mimetype): - m = re.search("""]*\?>""", - self.content) - if m: - encoding = m.group(1) - - # Format defaults - if self.mimetype == 'application/json' and not encoding: - # The default encoding for JSON - encoding = 'utf-8' - - elif self.mimetype == 'application/xml' and not encoding: - # The default for 'application/xml' - encoding = 'utf-8' - - if encoding: - encoding = encoding.lower() - - return encoding - - -def request(method, url, params=None, data=None, headers=None, cookies=None, - files=None, auth=None, timeout=60, allow_redirects=False, - stream=False): - """Initiate an HTTP(S) request. Returns :class:`Response` object. - - :param method: 'GET' or 'POST' - :type method: unicode - :param url: URL to open - :type url: unicode - :param params: mapping of URL parameters - :type params: dict - :param data: mapping of form data ``{'field_name': 'value'}`` or - :class:`str` - :type data: dict or str - :param headers: HTTP headers - :type headers: dict - :param cookies: cookies to send to server - :type cookies: dict - :param files: files to upload (see below). - :type files: dict - :param auth: username, password - :type auth: tuple - :param timeout: connection timeout limit in seconds - :type timeout: int - :param allow_redirects: follow redirections - :type allow_redirects: bool - :param stream: Stream content instead of fetching it all at once. - :type stream: bool - :returns: Response object - :rtype: :class:`Response` - - - The ``files`` argument is a dictionary:: - - {'fieldname' : { 'filename': 'blah.txt', - 'content': '', - 'mimetype': 'text/plain'} - } - - * ``fieldname`` is the name of the field in the HTML form. - * ``mimetype`` is optional. If not provided, :mod:`mimetypes` will - be used to guess the mimetype, or ``application/octet-stream`` - will be used. - - """ - # TODO: cookies - socket.setdefaulttimeout(timeout) - - # Default handlers - openers = [] - - if not allow_redirects: - openers.append(NoRedirectHandler()) - - if auth is not None: # Add authorisation handler - username, password = auth - password_manager = urllib.request.HTTPPasswordMgrWithDefaultRealm() - password_manager.add_password(None, url, username, password) - auth_manager = urllib.request.HTTPBasicAuthHandler(password_manager) - openers.append(auth_manager) - - # Install our custom chain of openers - opener = urllib.request.build_opener(*openers) - urllib.request.install_opener(opener) - - if not headers: - headers = CaseInsensitiveDictionary() - else: - headers = CaseInsensitiveDictionary(headers) - - if 'user-agent' not in headers: - headers['user-agent'] = USER_AGENT - - # Accept gzip-encoded content - encodings = [s.strip() for s in - headers.get('accept-encoding', '').split(',')] - if 'gzip' not in encodings: - encodings.append('gzip') - - headers['accept-encoding'] = ', '.join(encodings) - - # Force POST by providing an empty data string - if method == 'POST' and not data: - data = '' - - if files: - if not data: - data = {} - new_headers, data = encode_multipart_formdata(data, files) - headers.update(new_headers) - elif data and isinstance(data, dict): - data = urllib.parse.urlencode(str_dict(data)) - - # Make sure everything is encoded text - headers = str_dict(headers) - - if isinstance(url, unicode): - url = url.encode('utf-8') - - if params: # GET args (POST args are handled in encode_multipart_formdata) - - scheme, netloc, path, query, fragment = urllib.parse.urlsplit(url) - - if query: # Combine query string and `params` - url_params = urllib.parse.parse_qs(query) - # `params` take precedence over URL query string - url_params.update(params) - params = url_params - - query = urllib.parse.urlencode(str_dict(params), doseq=True) - url = urllib.parse.urlunsplit((scheme, netloc, path, query, fragment)) - - req = urllib.request.Request(url, data, headers) - return Response(req, stream) - - -def get(url, params=None, headers=None, cookies=None, auth=None, - timeout=60, allow_redirects=True, stream=False): - """Initiate a GET request. Arguments as for :func:`request`. - - :returns: :class:`Response` instance - - """ - return request('GET', url, params, headers=headers, cookies=cookies, - auth=auth, timeout=timeout, allow_redirects=allow_redirects, - stream=stream) - - -def post(url, params=None, data=None, headers=None, cookies=None, files=None, - auth=None, timeout=60, allow_redirects=False, stream=False): - """Initiate a POST request. Arguments as for :func:`request`. - - :returns: :class:`Response` instance - - """ - return request('POST', url, params, data, headers, cookies, files, auth, - timeout, allow_redirects, stream) - - -def encode_multipart_formdata(fields, files): - """Encode form data (``fields``) and ``files`` for POST request. - - :param fields: mapping of ``{name : value}`` pairs for normal form fields. - :type fields: dict - :param files: dictionary of fieldnames/files elements for file data. - See below for details. - :type files: dict of :class:`dict` - :returns: ``(headers, body)`` ``headers`` is a - :class:`dict` of HTTP headers - :rtype: 2-tuple ``(dict, str)`` - - The ``files`` argument is a dictionary:: - - {'fieldname' : { 'filename': 'blah.txt', - 'content': '', - 'mimetype': 'text/plain'} - } - - - ``fieldname`` is the name of the field in the HTML form. - - ``mimetype`` is optional. If not provided, :mod:`mimetypes` will - be used to guess the mimetype, or ``application/octet-stream`` - will be used. - - """ - def get_content_type(filename): - """Return or guess mimetype of ``filename``. - - :param filename: filename of file - :type filename: unicode/str - :returns: mime-type, e.g. ``text/html`` - :rtype: str - - """ - - return mimetypes.guess_type(filename)[0] or 'application/octet-stream' - - boundary = '-----' + ''.join(random.choice(BOUNDARY_CHARS) - for i in range(30)) - CRLF = '\r\n' - output = [] - - # Normal form fields - for (name, value) in fields.items(): - if isinstance(name, unicode): - name = name.encode('utf-8') - if isinstance(value, unicode): - value = value.encode('utf-8') - output.append('--' + boundary) - output.append('Content-Disposition: form-data; name="%s"' % name) - output.append('') - output.append(value) - - # Files to upload - for name, d in files.items(): - filename = d[u'filename'] - content = d[u'content'] - if u'mimetype' in d: - mimetype = d[u'mimetype'] - else: - mimetype = get_content_type(filename) - if isinstance(name, unicode): - name = name.encode('utf-8') - if isinstance(filename, unicode): - filename = filename.encode('utf-8') - if isinstance(mimetype, unicode): - mimetype = mimetype.encode('utf-8') - output.append('--' + boundary) - output.append('Content-Disposition: form-data; ' - 'name="%s"; filename="%s"' % (name, filename)) - output.append('Content-Type: %s' % mimetype) - output.append('') - output.append(content) - - output.append('--' + boundary + '--') - output.append('') - body = CRLF.join(output) - headers = { - 'Content-Type': 'multipart/form-data; boundary=%s' % boundary, - 'Content-Length': str(len(body)), - } - return (headers, body) \ No newline at end of file diff --git a/src/lib/workflow_old/web_old.py b/src/lib/workflow_old/web_old.py deleted file mode 100644 index 0781911..0000000 --- a/src/lib/workflow_old/web_old.py +++ /dev/null @@ -1,685 +0,0 @@ -# encoding: utf-8 -# -# Copyright (c) 2014 Dean Jackson -# -# MIT Licence. See http://opensource.org/licenses/MIT -# -# Created on 2014-02-15 -# - -"""Lightweight HTTP library with a requests-like interface.""" - -import codecs -import json -import mimetypes -import os -import random -import re -import socket -import string -import unicodedata -import urllib -import urllib2 -import urlparse -import zlib - - -USER_AGENT = u'Alfred-Workflow/1.36 (+http://www.deanishe.net/alfred-workflow)' - -# Valid characters for multipart form data boundaries -BOUNDARY_CHARS = string.digits + string.ascii_letters - -# HTTP response codes -RESPONSES = { - 100: 'Continue', - 101: 'Switching Protocols', - 200: 'OK', - 201: 'Created', - 202: 'Accepted', - 203: 'Non-Authoritative Information', - 204: 'No Content', - 205: 'Reset Content', - 206: 'Partial Content', - 300: 'Multiple Choices', - 301: 'Moved Permanently', - 302: 'Found', - 303: 'See Other', - 304: 'Not Modified', - 305: 'Use Proxy', - 307: 'Temporary Redirect', - 400: 'Bad Request', - 401: 'Unauthorized', - 402: 'Payment Required', - 403: 'Forbidden', - 404: 'Not Found', - 405: 'Method Not Allowed', - 406: 'Not Acceptable', - 407: 'Proxy Authentication Required', - 408: 'Request Timeout', - 409: 'Conflict', - 410: 'Gone', - 411: 'Length Required', - 412: 'Precondition Failed', - 413: 'Request Entity Too Large', - 414: 'Request-URI Too Long', - 415: 'Unsupported Media Type', - 416: 'Requested Range Not Satisfiable', - 417: 'Expectation Failed', - 500: 'Internal Server Error', - 501: 'Not Implemented', - 502: 'Bad Gateway', - 503: 'Service Unavailable', - 504: 'Gateway Timeout', - 505: 'HTTP Version Not Supported' -} - - -def str_dict(dic): - """Convert keys and values in ``dic`` into UTF-8-encoded :class:`str`. - - :param dic: Mapping of Unicode strings - :type dic: dict - :returns: Dictionary containing only UTF-8 strings - :rtype: dict - - """ - if isinstance(dic, CaseInsensitiveDictionary): - dic2 = CaseInsensitiveDictionary() - else: - dic2 = {} - for k, v in dic.items(): - if isinstance(k, unicode): - k = k.encode('utf-8') - if isinstance(v, unicode): - v = v.encode('utf-8') - dic2[k] = v - return dic2 - - -class NoRedirectHandler(urllib2.HTTPRedirectHandler): - """Prevent redirections.""" - - def redirect_request(self, *args): - """Ignore redirect.""" - return None - - -# Adapted from https://gist.github.com/babakness/3901174 -class CaseInsensitiveDictionary(dict): - """Dictionary with caseless key search. - - Enables case insensitive searching while preserving case sensitivity - when keys are listed, ie, via keys() or items() methods. - - Works by storing a lowercase version of the key as the new key and - stores the original key-value pair as the key's value - (values become dictionaries). - - """ - - def __init__(self, initval=None): - """Create new case-insensitive dictionary.""" - if isinstance(initval, dict): - for key, value in initval.iteritems(): - self.__setitem__(key, value) - - elif isinstance(initval, list): - for (key, value) in initval: - self.__setitem__(key, value) - - def __contains__(self, key): - return dict.__contains__(self, key.lower()) - - def __getitem__(self, key): - return dict.__getitem__(self, key.lower())['val'] - - def __setitem__(self, key, value): - return dict.__setitem__(self, key.lower(), {'key': key, 'val': value}) - - def get(self, key, default=None): - """Return value for case-insensitive key or default.""" - try: - v = dict.__getitem__(self, key.lower()) - except KeyError: - return default - else: - return v['val'] - - def update(self, other): - """Update values from other ``dict``.""" - for k, v in other.items(): - self[k] = v - - def items(self): - """Return ``(key, value)`` pairs.""" - return [(v['key'], v['val']) for v in dict.itervalues(self)] - - def keys(self): - """Return original keys.""" - return [v['key'] for v in dict.itervalues(self)] - - def values(self): - """Return all values.""" - return [v['val'] for v in dict.itervalues(self)] - - def iteritems(self): - """Iterate over ``(key, value)`` pairs.""" - for v in dict.itervalues(self): - yield v['key'], v['val'] - - def iterkeys(self): - """Iterate over original keys.""" - for v in dict.itervalues(self): - yield v['key'] - - def itervalues(self): - """Interate over values.""" - for v in dict.itervalues(self): - yield v['val'] - - -class Response(object): - """ - Returned by :func:`request` / :func:`get` / :func:`post` functions. - - Simplified version of the ``Response`` object in the ``requests`` library. - - >>> r = request('http://www.google.com') - >>> r.status_code - 200 - >>> r.encoding - ISO-8859-1 - >>> r.content # bytes - ... - >>> r.text # unicode, decoded according to charset in HTTP header/meta tag - u' ...' - >>> r.json() # content parsed as JSON - - """ - - def __init__(self, request, stream=False): - """Call `request` with :mod:`urllib2` and process results. - - :param request: :class:`urllib2.Request` instance - :param stream: Whether to stream response or retrieve it all at once - :type stream: bool - - """ - self.request = request - self._stream = stream - self.url = None - self.raw = None - self._encoding = None - self.error = None - self.status_code = None - self.reason = None - self.headers = CaseInsensitiveDictionary() - self._content = None - self._content_loaded = False - self._gzipped = False - - # Execute query - try: - self.raw = urllib2.urlopen(request) - except urllib2.HTTPError as err: - self.error = err - try: - self.url = err.geturl() - # sometimes (e.g. when authentication fails) - # urllib can't get a URL from an HTTPError - # This behaviour changes across Python versions, - # so no test cover (it isn't important). - except AttributeError: # pragma: no cover - pass - self.status_code = err.code - else: - self.status_code = self.raw.getcode() - self.url = self.raw.geturl() - self.reason = RESPONSES.get(self.status_code) - - # Parse additional info if request succeeded - if not self.error: - headers = self.raw.info() - self.transfer_encoding = headers.getencoding() - self.mimetype = headers.gettype() - for key in headers.keys(): - self.headers[key.lower()] = headers.get(key) - - # Is content gzipped? - # Transfer-Encoding appears to not be used in the wild - # (contrary to the HTTP standard), but no harm in testing - # for it - if 'gzip' in headers.get('content-encoding', '') or \ - 'gzip' in headers.get('transfer-encoding', ''): - self._gzipped = True - - @property - def stream(self): - """Whether response is streamed. - - Returns: - bool: `True` if response is streamed. - - """ - return self._stream - - @stream.setter - def stream(self, value): - if self._content_loaded: - raise RuntimeError("`content` has already been read from " - "this Response.") - - self._stream = value - - def json(self): - """Decode response contents as JSON. - - :returns: object decoded from JSON - :rtype: list, dict or unicode - - """ - return json.loads(self.content, self.encoding or 'utf-8') - - @property - def encoding(self): - """Text encoding of document or ``None``. - - :returns: Text encoding if found. - :rtype: str or ``None`` - - """ - if not self._encoding: - self._encoding = self._get_encoding() - - return self._encoding - - @property - def content(self): - """Raw content of response (i.e. bytes). - - :returns: Body of HTTP response - :rtype: str - - """ - if not self._content: - - # Decompress gzipped content - if self._gzipped: - decoder = zlib.decompressobj(16 + zlib.MAX_WBITS) - self._content = decoder.decompress(self.raw.read()) - - else: - self._content = self.raw.read() - - self._content_loaded = True - - return self._content - - @property - def text(self): - """Unicode-decoded content of response body. - - If no encoding can be determined from HTTP headers or the content - itself, the encoded response body will be returned instead. - - :returns: Body of HTTP response - :rtype: unicode or str - - """ - if self.encoding: - return unicodedata.normalize('NFC', unicode(self.content, - self.encoding)) - return self.content - - def iter_content(self, chunk_size=4096, decode_unicode=False): - """Iterate over response data. - - .. versionadded:: 1.6 - - :param chunk_size: Number of bytes to read into memory - :type chunk_size: int - :param decode_unicode: Decode to Unicode using detected encoding - :type decode_unicode: bool - :returns: iterator - - """ - if not self.stream: - raise RuntimeError("You cannot call `iter_content` on a " - "Response unless you passed `stream=True`" - " to `get()`/`post()`/`request()`.") - - if self._content_loaded: - raise RuntimeError( - "`content` has already been read from this Response.") - - def decode_stream(iterator, r): - dec = codecs.getincrementaldecoder(r.encoding)(errors='replace') - - for chunk in iterator: - data = dec.decode(chunk) - if data: - yield data - - data = dec.decode(b'', final=True) - if data: # pragma: no cover - yield data - - def generate(): - if self._gzipped: - decoder = zlib.decompressobj(16 + zlib.MAX_WBITS) - - while True: - chunk = self.raw.read(chunk_size) - if not chunk: - break - - if self._gzipped: - chunk = decoder.decompress(chunk) - - yield chunk - - chunks = generate() - - if decode_unicode and self.encoding: - chunks = decode_stream(chunks, self) - - return chunks - - def save_to_path(self, filepath): - """Save retrieved data to file at ``filepath``. - - .. versionadded: 1.9.6 - - :param filepath: Path to save retrieved data. - - """ - filepath = os.path.abspath(filepath) - dirname = os.path.dirname(filepath) - if not os.path.exists(dirname): - os.makedirs(dirname) - - self.stream = True - - with open(filepath, 'wb') as fileobj: - for data in self.iter_content(): - fileobj.write(data) - - def raise_for_status(self): - """Raise stored error if one occurred. - - error will be instance of :class:`urllib2.HTTPError` - """ - if self.error is not None: - raise self.error - return - - def _get_encoding(self): - """Get encoding from HTTP headers or content. - - :returns: encoding or `None` - :rtype: unicode or ``None`` - - """ - headers = self.raw.info() - encoding = None - - if headers.getparam('charset'): - encoding = headers.getparam('charset') - - # HTTP Content-Type header - for param in headers.getplist(): - if param.startswith('charset='): - encoding = param[8:] - break - - if not self.stream: # Try sniffing response content - # Encoding declared in document should override HTTP headers - if self.mimetype == 'text/html': # sniff HTML headers - m = re.search(r"""""", - self.content) - if m: - encoding = m.group(1) - - elif ((self.mimetype.startswith('application/') - or self.mimetype.startswith('text/')) - and 'xml' in self.mimetype): - m = re.search(r"""]*\?>""", - self.content) - if m: - encoding = m.group(1) - - # Format defaults - if self.mimetype == 'application/json' and not encoding: - # The default encoding for JSON - encoding = 'utf-8' - - elif self.mimetype == 'application/xml' and not encoding: - # The default for 'application/xml' - encoding = 'utf-8' - - if encoding: - encoding = encoding.lower() - - return encoding - - -def request(method, url, params=None, data=None, headers=None, cookies=None, - files=None, auth=None, timeout=60, allow_redirects=False, - stream=False): - """Initiate an HTTP(S) request. Returns :class:`Response` object. - - :param method: 'GET' or 'POST' - :type method: unicode - :param url: URL to open - :type url: unicode - :param params: mapping of URL parameters - :type params: dict - :param data: mapping of form data ``{'field_name': 'value'}`` or - :class:`str` - :type data: dict or str - :param headers: HTTP headers - :type headers: dict - :param cookies: cookies to send to server - :type cookies: dict - :param files: files to upload (see below). - :type files: dict - :param auth: username, password - :type auth: tuple - :param timeout: connection timeout limit in seconds - :type timeout: int - :param allow_redirects: follow redirections - :type allow_redirects: bool - :param stream: Stream content instead of fetching it all at once. - :type stream: bool - :returns: Response object - :rtype: :class:`Response` - - - The ``files`` argument is a dictionary:: - - {'fieldname' : { 'filename': 'blah.txt', - 'content': '', - 'mimetype': 'text/plain'} - } - - * ``fieldname`` is the name of the field in the HTML form. - * ``mimetype`` is optional. If not provided, :mod:`mimetypes` will - be used to guess the mimetype, or ``application/octet-stream`` - will be used. - - """ - # TODO: cookies - socket.setdefaulttimeout(timeout) - - # Default handlers - openers = [] - - if not allow_redirects: - openers.append(NoRedirectHandler()) - - if auth is not None: # Add authorisation handler - username, password = auth - password_manager = urllib2.HTTPPasswordMgrWithDefaultRealm() - password_manager.add_password(None, url, username, password) - auth_manager = urllib2.HTTPBasicAuthHandler(password_manager) - openers.append(auth_manager) - - # Install our custom chain of openers - opener = urllib2.build_opener(*openers) - urllib2.install_opener(opener) - - if not headers: - headers = CaseInsensitiveDictionary() - else: - headers = CaseInsensitiveDictionary(headers) - - if 'user-agent' not in headers: - headers['user-agent'] = USER_AGENT - - # Accept gzip-encoded content - encodings = [s.strip() for s in - headers.get('accept-encoding', '').split(',')] - if 'gzip' not in encodings: - encodings.append('gzip') - - headers['accept-encoding'] = ', '.join(encodings) - - # Force POST by providing an empty data string - if method == 'POST' and not data: - data = '' - - if files: - if not data: - data = {} - new_headers, data = encode_multipart_formdata(data, files) - headers.update(new_headers) - elif data and isinstance(data, dict): - data = urllib.urlencode(str_dict(data)) - - # Make sure everything is encoded text - headers = str_dict(headers) - - if isinstance(url, unicode): - url = url.encode('utf-8') - - if params: # GET args (POST args are handled in encode_multipart_formdata) - - scheme, netloc, path, query, fragment = urlparse.urlsplit(url) - - if query: # Combine query string and `params` - url_params = urlparse.parse_qs(query) - # `params` take precedence over URL query string - url_params.update(params) - params = url_params - - query = urllib.urlencode(str_dict(params), doseq=True) - url = urlparse.urlunsplit((scheme, netloc, path, query, fragment)) - - req = urllib2.Request(url, data, headers) - return Response(req, stream) - - -def get(url, params=None, headers=None, cookies=None, auth=None, - timeout=60, allow_redirects=True, stream=False): - """Initiate a GET request. Arguments as for :func:`request`. - - :returns: :class:`Response` instance - - """ - return request('GET', url, params, headers=headers, cookies=cookies, - auth=auth, timeout=timeout, allow_redirects=allow_redirects, - stream=stream) - - -def post(url, params=None, data=None, headers=None, cookies=None, files=None, - auth=None, timeout=60, allow_redirects=False, stream=False): - """Initiate a POST request. Arguments as for :func:`request`. - - :returns: :class:`Response` instance - - """ - return request('POST', url, params, data, headers, cookies, files, auth, - timeout, allow_redirects, stream) - - -def encode_multipart_formdata(fields, files): - """Encode form data (``fields``) and ``files`` for POST request. - - :param fields: mapping of ``{name : value}`` pairs for normal form fields. - :type fields: dict - :param files: dictionary of fieldnames/files elements for file data. - See below for details. - :type files: dict of :class:`dict` - :returns: ``(headers, body)`` ``headers`` is a - :class:`dict` of HTTP headers - :rtype: 2-tuple ``(dict, str)`` - - The ``files`` argument is a dictionary:: - - {'fieldname' : { 'filename': 'blah.txt', - 'content': '', - 'mimetype': 'text/plain'} - } - - - ``fieldname`` is the name of the field in the HTML form. - - ``mimetype`` is optional. If not provided, :mod:`mimetypes` will - be used to guess the mimetype, or ``application/octet-stream`` - will be used. - - """ - def get_content_type(filename): - """Return or guess mimetype of ``filename``. - - :param filename: filename of file - :type filename: unicode/str - :returns: mime-type, e.g. ``text/html`` - :rtype: str - - """ - return mimetypes.guess_type(filename)[0] or 'application/octet-stream' - - boundary = '-----' + ''.join(random.choice(BOUNDARY_CHARS) - for i in range(30)) - CRLF = '\r\n' - output = [] - - # Normal form fields - for (name, value) in fields.items(): - if isinstance(name, unicode): - name = name.encode('utf-8') - if isinstance(value, unicode): - value = value.encode('utf-8') - output.append('--' + boundary) - output.append('Content-Disposition: form-data; name="%s"' % name) - output.append('') - output.append(value) - - # Files to upload - for name, d in files.items(): - filename = d[u'filename'] - content = d[u'content'] - if u'mimetype' in d: - mimetype = d[u'mimetype'] - else: - mimetype = get_content_type(filename) - if isinstance(name, unicode): - name = name.encode('utf-8') - if isinstance(filename, unicode): - filename = filename.encode('utf-8') - if isinstance(mimetype, unicode): - mimetype = mimetype.encode('utf-8') - output.append('--' + boundary) - output.append('Content-Disposition: form-data; ' - 'name="%s"; filename="%s"' % (name, filename)) - output.append('Content-Type: %s' % mimetype) - output.append('') - output.append(content) - - output.append('--' + boundary + '--') - output.append('') - body = CRLF.join(output) - headers = { - 'Content-Type': 'multipart/form-data; boundary=%s' % boundary, - 'Content-Length': str(len(body)), - } - return (headers, body) diff --git a/src/lib/workflow_old/workflow.py b/src/lib/workflow_old/workflow.py deleted file mode 100644 index 04a699b..0000000 --- a/src/lib/workflow_old/workflow.py +++ /dev/null @@ -1,2817 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -# -# Copyright (c) 2014 Dean Jackson -# -# MIT Licence. See http://opensource.org/licenses/MIT -# -# Created on 2014-02-15 -# - -"""The :class:`Workflow` object is the main interface to this library. - -:class:`Workflow` is targeted at Alfred 2. Use -:class:`~workflow.Workflow3` if you want to use Alfred 3's new -features, such as :ref:`workflow variables ` or -more powerful modifiers. - -See :ref:`setup` in the :ref:`user-manual` for an example of how to set -up your Python script to best utilise the :class:`Workflow` object. - -""" - -from __future__ import print_function, unicode_literals - -import binascii -import json -import logging -import logging.handlers -import os -import pickle -import plistlib -import re -import shutil -import string -import subprocess -import sys -import time -import unicodedata -from copy import deepcopy - -try: - import xml.etree.cElementTree as ET -except ImportError: # pragma: no cover - import xml.etree.ElementTree as ET - -from workflow.util import atomic_writer, uninterruptible,LockFile - -# from .util import ( -# # imported to maintain API -# atomic_writer, -# LockFile, -# uninterruptible, -# ) - -#: Sentinel for properties that haven't been set yet (that might -#: correctly have the value ``None``) -UNSET = object() - -#################################################################### -# Standard system icons -#################################################################### - -# These icons are default macOS icons. They are super-high quality, and -# will be familiar to users. -# This library uses `ICON_ERROR` when a workflow dies in flames, so -# in my own workflows, I use `ICON_WARNING` for less fatal errors -# (e.g. bad user input, no results etc.) - -# The system icons are all in this directory. There are many more than -# are listed here - -ICON_ROOT = '/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources' - -ICON_ACCOUNT = os.path.join(ICON_ROOT, 'Accounts.icns') -ICON_BURN = os.path.join(ICON_ROOT, 'BurningIcon.icns') -ICON_CLOCK = os.path.join(ICON_ROOT, 'Clock.icns') -ICON_COLOR = os.path.join(ICON_ROOT, 'ProfileBackgroundColor.icns') -ICON_COLOUR = ICON_COLOR # Queen's English, if you please -ICON_EJECT = os.path.join(ICON_ROOT, 'EjectMediaIcon.icns') -# Shown when a workflow throws an error -ICON_ERROR = os.path.join(ICON_ROOT, 'AlertStopIcon.icns') -ICON_FAVORITE = os.path.join(ICON_ROOT, 'ToolbarFavoritesIcon.icns') -ICON_FAVOURITE = ICON_FAVORITE -ICON_GROUP = os.path.join(ICON_ROOT, 'GroupIcon.icns') -ICON_HELP = os.path.join(ICON_ROOT, 'HelpIcon.icns') -ICON_HOME = os.path.join(ICON_ROOT, 'HomeFolderIcon.icns') -ICON_INFO = os.path.join(ICON_ROOT, 'ToolbarInfo.icns') -ICON_NETWORK = os.path.join(ICON_ROOT, 'GenericNetworkIcon.icns') -ICON_NOTE = os.path.join(ICON_ROOT, 'AlertNoteIcon.icns') -ICON_SETTINGS = os.path.join(ICON_ROOT, 'ToolbarAdvanced.icns') -ICON_SWIRL = os.path.join(ICON_ROOT, 'ErasingIcon.icns') -ICON_SWITCH = os.path.join(ICON_ROOT, 'General.icns') -ICON_SYNC = os.path.join(ICON_ROOT, 'Sync.icns') -ICON_TRASH = os.path.join(ICON_ROOT, 'TrashIcon.icns') -ICON_USER = os.path.join(ICON_ROOT, 'UserIcon.icns') -ICON_WARNING = os.path.join(ICON_ROOT, 'AlertCautionIcon.icns') -ICON_WEB = os.path.join(ICON_ROOT, 'BookmarkIcon.icns') - -#################################################################### -# non-ASCII to ASCII diacritic folding. -# Used by `fold_to_ascii` method -#################################################################### - -ASCII_REPLACEMENTS = { - 'À': 'A', - 'Á': 'A', - 'Â': 'A', - 'Ã': 'A', - 'Ä': 'A', - 'Å': 'A', - 'Æ': 'AE', - 'Ç': 'C', - 'È': 'E', - 'É': 'E', - 'Ê': 'E', - 'Ë': 'E', - 'Ì': 'I', - 'Í': 'I', - 'Î': 'I', - 'Ï': 'I', - 'Ð': 'D', - 'Ñ': 'N', - 'Ò': 'O', - 'Ó': 'O', - 'Ô': 'O', - 'Õ': 'O', - 'Ö': 'O', - 'Ø': 'O', - 'Ù': 'U', - 'Ú': 'U', - 'Û': 'U', - 'Ü': 'U', - 'Ý': 'Y', - 'Þ': 'Th', - 'ß': 'ss', - 'à': 'a', - 'á': 'a', - 'â': 'a', - 'ã': 'a', - 'ä': 'a', - 'å': 'a', - 'æ': 'ae', - 'ç': 'c', - 'è': 'e', - 'é': 'e', - 'ê': 'e', - 'ë': 'e', - 'ì': 'i', - 'í': 'i', - 'î': 'i', - 'ï': 'i', - 'ð': 'd', - 'ñ': 'n', - 'ò': 'o', - 'ó': 'o', - 'ô': 'o', - 'õ': 'o', - 'ö': 'o', - 'ø': 'o', - 'ù': 'u', - 'ú': 'u', - 'û': 'u', - 'ü': 'u', - 'ý': 'y', - 'þ': 'th', - 'ÿ': 'y', - 'Ł': 'L', - 'ł': 'l', - 'Ń': 'N', - 'ń': 'n', - 'Ņ': 'N', - 'ņ': 'n', - 'Ň': 'N', - 'ň': 'n', - 'Ŋ': 'ng', - 'ŋ': 'NG', - 'Ō': 'O', - 'ō': 'o', - 'Ŏ': 'O', - 'ŏ': 'o', - 'Ő': 'O', - 'ő': 'o', - 'Œ': 'OE', - 'œ': 'oe', - 'Ŕ': 'R', - 'ŕ': 'r', - 'Ŗ': 'R', - 'ŗ': 'r', - 'Ř': 'R', - 'ř': 'r', - 'Ś': 'S', - 'ś': 's', - 'Ŝ': 'S', - 'ŝ': 's', - 'Ş': 'S', - 'ş': 's', - 'Š': 'S', - 'š': 's', - 'Ţ': 'T', - 'ţ': 't', - 'Ť': 'T', - 'ť': 't', - 'Ŧ': 'T', - 'ŧ': 't', - 'Ũ': 'U', - 'ũ': 'u', - 'Ū': 'U', - 'ū': 'u', - 'Ŭ': 'U', - 'ŭ': 'u', - 'Ů': 'U', - 'ů': 'u', - 'Ű': 'U', - 'ű': 'u', - 'Ŵ': 'W', - 'ŵ': 'w', - 'Ŷ': 'Y', - 'ŷ': 'y', - 'Ÿ': 'Y', - 'Ź': 'Z', - 'ź': 'z', - 'Ż': 'Z', - 'ż': 'z', - 'Ž': 'Z', - 'ž': 'z', - 'ſ': 's', - 'Α': 'A', - 'Β': 'B', - 'Γ': 'G', - 'Δ': 'D', - 'Ε': 'E', - 'Ζ': 'Z', - 'Η': 'E', - 'Θ': 'Th', - 'Ι': 'I', - 'Κ': 'K', - 'Λ': 'L', - 'Μ': 'M', - 'Ν': 'N', - 'Ξ': 'Ks', - 'Ο': 'O', - 'Π': 'P', - 'Ρ': 'R', - 'Σ': 'S', - 'Τ': 'T', - 'Υ': 'U', - 'Φ': 'Ph', - 'Χ': 'Kh', - 'Ψ': 'Ps', - 'Ω': 'O', - 'α': 'a', - 'β': 'b', - 'γ': 'g', - 'δ': 'd', - 'ε': 'e', - 'ζ': 'z', - 'η': 'e', - 'θ': 'th', - 'ι': 'i', - 'κ': 'k', - 'λ': 'l', - 'μ': 'm', - 'ν': 'n', - 'ξ': 'x', - 'ο': 'o', - 'π': 'p', - 'ρ': 'r', - 'ς': 's', - 'σ': 's', - 'τ': 't', - 'υ': 'u', - 'φ': 'ph', - 'χ': 'kh', - 'ψ': 'ps', - 'ω': 'o', - 'А': 'A', - 'Б': 'B', - 'В': 'V', - 'Г': 'G', - 'Д': 'D', - 'Е': 'E', - 'Ж': 'Zh', - 'З': 'Z', - 'И': 'I', - 'Й': 'I', - 'К': 'K', - 'Л': 'L', - 'М': 'M', - 'Н': 'N', - 'О': 'O', - 'П': 'P', - 'Р': 'R', - 'С': 'S', - 'Т': 'T', - 'У': 'U', - 'Ф': 'F', - 'Х': 'Kh', - 'Ц': 'Ts', - 'Ч': 'Ch', - 'Ш': 'Sh', - 'Щ': 'Shch', - 'Ъ': "'", - 'Ы': 'Y', - 'Ь': "'", - 'Э': 'E', - 'Ю': 'Iu', - 'Я': 'Ia', - 'а': 'a', - 'б': 'b', - 'в': 'v', - 'г': 'g', - 'д': 'd', - 'е': 'e', - 'ж': 'zh', - 'з': 'z', - 'и': 'i', - 'й': 'i', - 'к': 'k', - 'л': 'l', - 'м': 'm', - 'н': 'n', - 'о': 'o', - 'п': 'p', - 'р': 'r', - 'с': 's', - 'т': 't', - 'у': 'u', - 'ф': 'f', - 'х': 'kh', - 'ц': 'ts', - 'ч': 'ch', - 'ш': 'sh', - 'щ': 'shch', - 'ъ': "'", - 'ы': 'y', - 'ь': "'", - 'э': 'e', - 'ю': 'iu', - 'я': 'ia', - # 'ᴀ': '', - # 'ᴁ': '', - # 'ᴂ': '', - # 'ᴃ': '', - # 'ᴄ': '', - # 'ᴅ': '', - # 'ᴆ': '', - # 'ᴇ': '', - # 'ᴈ': '', - # 'ᴉ': '', - # 'ᴊ': '', - # 'ᴋ': '', - # 'ᴌ': '', - # 'ᴍ': '', - # 'ᴎ': '', - # 'ᴏ': '', - # 'ᴐ': '', - # 'ᴑ': '', - # 'ᴒ': '', - # 'ᴓ': '', - # 'ᴔ': '', - # 'ᴕ': '', - # 'ᴖ': '', - # 'ᴗ': '', - # 'ᴘ': '', - # 'ᴙ': '', - # 'ᴚ': '', - # 'ᴛ': '', - # 'ᴜ': '', - # 'ᴝ': '', - # 'ᴞ': '', - # 'ᴟ': '', - # 'ᴠ': '', - # 'ᴡ': '', - # 'ᴢ': '', - # 'ᴣ': '', - # 'ᴤ': '', - # 'ᴥ': '', - 'ᴦ': 'G', - 'ᴧ': 'L', - 'ᴨ': 'P', - 'ᴩ': 'R', - 'ᴪ': 'PS', - 'ẞ': 'Ss', - 'Ỳ': 'Y', - 'ỳ': 'y', - 'Ỵ': 'Y', - 'ỵ': 'y', - 'Ỹ': 'Y', - 'ỹ': 'y', -} - -#################################################################### -# Smart-to-dumb punctuation mapping -#################################################################### - -DUMB_PUNCTUATION = { - '‘': "'", - '’': "'", - '‚': "'", - '“': '"', - '”': '"', - '„': '"', - '–': '-', - '—': '-' -} - -#################################################################### -# Used by `Workflow.filter` -#################################################################### - -# Anchor characters in a name -#: Characters that indicate the beginning of a "word" in CamelCase -INITIALS = string.ascii_uppercase + string.digits - -#: Split on non-letters, numbers -split_on_delimiters = re.compile('[^a-zA-Z0-9]').split - -# Match filter flags -#: Match items that start with ``query`` -MATCH_STARTSWITH = 1 -#: Match items whose capital letters start with ``query`` -MATCH_CAPITALS = 2 -#: Match items with a component "word" that matches ``query`` -MATCH_ATOM = 4 -#: Match items whose initials (based on atoms) start with ``query`` -MATCH_INITIALS_STARTSWITH = 8 -#: Match items whose initials (based on atoms) contain ``query`` -MATCH_INITIALS_CONTAIN = 16 -#: Combination of :const:`MATCH_INITIALS_STARTSWITH` and -#: :const:`MATCH_INITIALS_CONTAIN` -MATCH_INITIALS = 24 -#: Match items if ``query`` is a substring -MATCH_SUBSTRING = 32 -#: Match items if all characters in ``query`` appear in the item in order -MATCH_ALLCHARS = 64 -#: Combination of all other ``MATCH_*`` constants -MATCH_ALL = 127 - -#################################################################### -# Used by `Workflow.check_update` -#################################################################### - -# Number of days to wait between checking for updates to the workflow -DEFAULT_UPDATE_FREQUENCY = 1 - - -#################################################################### -# Keychain access errors -#################################################################### - - -class KeychainError(Exception): - """Raised for unknown Keychain errors. - - Raised by methods :meth:`Workflow.save_password`, - :meth:`Workflow.get_password` and :meth:`Workflow.delete_password` - when ``security`` CLI app returns an unknown error code. - - """ - - -class PasswordNotFound(KeychainError): - """Password not in Keychain. - - Raised by method :meth:`Workflow.get_password` when ``account`` - is unknown to the Keychain. - - """ - - -class PasswordExists(KeychainError): - """Raised when trying to overwrite an existing account password. - - You should never receive this error: it is used internally - by the :meth:`Workflow.save_password` method to know if it needs - to delete the old password first (a Keychain implementation detail). - - """ - - -#################################################################### -# Helper functions -#################################################################### - -def isascii(text): - """Test if ``text`` contains only ASCII characters. - - :param text: text to test for ASCII-ness - :type text: ``unicode`` - :returns: ``True`` if ``text`` contains only ASCII characters - :rtype: ``Boolean`` - - """ - try: - text.encode('ascii') - except UnicodeEncodeError: - return False - return True - - -#################################################################### -# Implementation classes -#################################################################### - -class SerializerManager(object): - """Contains registered serializers. - - .. versionadded:: 1.8 - - A configured instance of this class is available at - :attr:`workflow.manager`. - - Use :meth:`register()` to register new (or replace - existing) serializers, which you can specify by name when calling - :class:`~workflow.Workflow` data storage methods. - - See :ref:`guide-serialization` and :ref:`guide-persistent-data` - for further information. - - """ - - def __init__(self): - """Create new SerializerManager object.""" - self._serializers = {} - - def register(self, name, serializer): - """Register ``serializer`` object under ``name``. - - Raises :class:`AttributeError` if ``serializer`` in invalid. - - .. note:: - - ``name`` will be used as the file extension of the saved files. - - :param name: Name to register ``serializer`` under - :type name: ``unicode`` or ``str`` - :param serializer: object with ``load()`` and ``dump()`` - methods - - """ - # Basic validation - getattr(serializer, 'load') - getattr(serializer, 'dump') - - self._serializers[name] = serializer - - def serializer(self, name): - """Return serializer object for ``name``. - - :param name: Name of serializer to return - :type name: ``unicode`` or ``str`` - :returns: serializer object or ``None`` if no such serializer - is registered. - - """ - return self._serializers.get(name) - - def unregister(self, name): - """Remove registered serializer with ``name``. - - Raises a :class:`ValueError` if there is no such registered - serializer. - - :param name: Name of serializer to remove - :type name: ``unicode`` or ``str`` - :returns: serializer object - - """ - if name not in self._serializers: - raise ValueError('No such serializer registered : {0}'.format( - name)) - - serializer = self._serializers[name] - del self._serializers[name] - - return serializer - - @property - def serializers(self): - """Return names of registered serializers.""" - return sorted(self._serializers.keys()) - - -class JSONSerializer(object): - """Wrapper around :mod:`json`. Sets ``indent`` and ``encoding``. - - .. versionadded:: 1.8 - - Use this serializer if you need readable data files. JSON doesn't - support Python objects as well as ``cPickle``/``pickle``, so be - careful which data you try to serialize as JSON. - - """ - - @classmethod - def load(cls, file_obj): - """Load serialized object from open JSON file. - - .. versionadded:: 1.8 - - :param file_obj: file handle - :type file_obj: ``file`` object - :returns: object loaded from JSON file - :rtype: object - - """ - return json.load(file_obj) - - @classmethod - def dump(cls, obj, file_obj): - """Serialize object ``obj`` to open JSON file. - - .. versionadded:: 1.8 - - :param obj: Python object to serialize - :type obj: JSON-serializable data structure - :param file_obj: file handle - :type file_obj: ``file`` object - - """ - return json.dump(obj, file_obj, indent=2, encoding='utf-8') - - -class CPickleSerializer(object): - """Wrapper around :mod:`cPickle`. Sets ``protocol``. - - .. versionadded:: 1.8 - - This is the default serializer and the best combination of speed and - flexibility. - - """ - - @classmethod - def load(cls, file_obj): - """Load serialized object from open pickle file. - - .. versionadded:: 1.8 - - :param file_obj: file handle - :type file_obj: ``file`` object - :returns: object loaded from pickle file - :rtype: object - - """ - return pickle.load(file_obj) - - @classmethod - def dump(cls, obj, file_obj): - """Serialize object ``obj`` to open pickle file. - - .. versionadded:: 1.8 - - :param obj: Python object to serialize - :type obj: Python object - :param file_obj: file handle - :type file_obj: ``file`` object - - """ - return pickle.dump(obj, file_obj, protocol=-1) - - -class PickleSerializer(object): - """Wrapper around :mod:`pickle`. Sets ``protocol``. - - .. versionadded:: 1.8 - - Use this serializer if you need to add custom pickling. - - """ - - @classmethod - def load(cls, file_obj): - """Load serialized object from open pickle file. - - .. versionadded:: 1.8 - - :param file_obj: file handle - :type file_obj: ``file`` object - :returns: object loaded from pickle file - :rtype: object - - """ - return pickle.load(file_obj) - - @classmethod - def dump(cls, obj, file_obj): - """Serialize object ``obj`` to open pickle file. - - .. versionadded:: 1.8 - - :param obj: Python object to serialize - :type obj: Python object - :param file_obj: file handle - :type file_obj: ``file`` object - - """ - return pickle.dump(obj, file_obj, protocol=-1) - - -# Set up default manager and register built-in serializers -manager = SerializerManager() -manager.register('cpickle', CPickleSerializer) -manager.register('pickle', PickleSerializer) -manager.register('json', JSONSerializer) - - -class Item(object): - """Represents a feedback item for Alfred. - - Generates Alfred-compliant XML for a single item. - - You probably shouldn't use this class directly, but via - :meth:`Workflow.add_item`. See :meth:`~Workflow.add_item` - for details of arguments. - - """ - - def __init__(self, title, subtitle='', modifier_subtitles=None, - arg=None, autocomplete=None, valid=False, uid=None, - icon=None, icontype=None, type=None, largetext=None, - copytext=None, quicklookurl=None): - """Same arguments as :meth:`Workflow.add_item`.""" - self.title = title - self.subtitle = subtitle - self.modifier_subtitles = modifier_subtitles or {} - self.arg = arg - self.autocomplete = autocomplete - self.valid = valid - self.uid = uid - self.icon = icon - self.icontype = icontype - self.type = type - self.largetext = largetext - self.copytext = copytext - self.quicklookurl = quicklookurl - - @property - def elem(self): - """Create and return feedback item for Alfred. - - :returns: :class:`ElementTree.Element ` - instance for this :class:`Item` instance. - - """ - # Attributes on element - attr = {} - if self.valid: - attr['valid'] = 'yes' - else: - attr['valid'] = 'no' - # Allow empty string for autocomplete. This is a useful value, - # as TABing the result will revert the query back to just the - # keyword - if self.autocomplete is not None: - attr['autocomplete'] = self.autocomplete - - # Optional attributes - for name in ('uid', 'type'): - value = getattr(self, name, None) - if value: - attr[name] = value - - root = ET.Element('item', attr) - ET.SubElement(root, 'title').text = self.title - ET.SubElement(root, 'subtitle').text = self.subtitle - - # Add modifier subtitles - for mod in ('cmd', 'ctrl', 'alt', 'shift', 'fn'): - if mod in self.modifier_subtitles: - ET.SubElement(root, 'subtitle', - {'mod': mod}).text = self.modifier_subtitles[mod] - - # Add arg as element instead of attribute on , as it's more - # flexible (newlines aren't allowed in attributes) - if self.arg: - ET.SubElement(root, 'arg').text = self.arg - - # Add icon if there is one - if self.icon: - if self.icontype: - attr = dict(type=self.icontype) - else: - attr = {} - ET.SubElement(root, 'icon', attr).text = self.icon - - if self.largetext: - ET.SubElement(root, 'text', - {'type': 'largetype'}).text = self.largetext - - if self.copytext: - ET.SubElement(root, 'text', - {'type': 'copy'}).text = self.copytext - - if self.quicklookurl: - ET.SubElement(root, 'quicklookurl').text = self.quicklookurl - - return root - - -class Settings(dict): - """A dictionary that saves itself when changed. - - Dictionary keys & values will be saved as a JSON file - at ``filepath``. If the file does not exist, the dictionary - (and settings file) will be initialised with ``defaults``. - - :param filepath: where to save the settings - :type filepath: :class:`unicode` - :param defaults: dict of default settings - :type defaults: :class:`dict` - - - An appropriate instance is provided by :class:`Workflow` instances at - :attr:`Workflow.settings`. - - """ - - def __init__(self, filepath, defaults=None): - """Create new :class:`Settings` object.""" - super(Settings, self).__init__() - self._filepath = filepath - self._nosave = False - self._original = {} - if os.path.exists(self._filepath): - self._load() - elif defaults: - for key, val in defaults.items(): - self[key] = val - self.save() # save default settings - - def _load(self): - """Load cached settings from JSON file `self._filepath`.""" - data = {} - with LockFile(self._filepath, 0.5): - with open(self._filepath, 'rb') as fp: - data.update(json.load(fp)) - - self._original = deepcopy(data) - - self._nosave = True - self.update(data) - self._nosave = False - - @uninterruptible - def save(self): - """Save settings to JSON file specified in ``self._filepath``. - - If you're using this class via :attr:`Workflow.settings`, which - you probably are, ``self._filepath`` will be ``settings.json`` - in your workflow's data directory (see :attr:`~Workflow.datadir`). - """ - if self._nosave: - return - - data = {} - data.update(self) - - with LockFile(self._filepath, 0.5): - with atomic_writer(self._filepath, 'w') as fp: # wb gives an error - json.dump(data, fp, sort_keys=True, indent=2) - #encoding='utf-8') - - # dict methods - def __setitem__(self, key, value): - """Implement :class:`dict` interface.""" - if self._original.get(key) != value: - super(Settings, self).__setitem__(key, value) - self.save() - - def __delitem__(self, key): - """Implement :class:`dict` interface.""" - super(Settings, self).__delitem__(key) - self.save() - - def update(self, *args, **kwargs): - """Override :class:`dict` method to save on update.""" - super(Settings, self).update(*args, **kwargs) - self.save() - - def setdefault(self, key, value=None): - """Override :class:`dict` method to save on update.""" - ret = super(Settings, self).setdefault(key, value) - self.save() - return ret - - -class Workflow(object): - """The ``Workflow`` object is the main interface to Alfred-Workflow. - - It provides APIs for accessing the Alfred/workflow environment, - storing & caching data, using Keychain, and generating Script - Filter feedback. - - ``Workflow`` is compatible with both Alfred 2 and 3. The - :class:`~workflow.Workflow3` subclass provides additional, - Alfred 3-only features, such as workflow variables. - - :param default_settings: default workflow settings. If no settings file - exists, :class:`Workflow.settings` will be pre-populated with - ``default_settings``. - :type default_settings: :class:`dict` - :param update_settings: settings for updating your workflow from - GitHub releases. The only required key is ``github_slug``, - whose value must take the form of ``username/repo``. - If specified, ``Workflow`` will check the repo's releases - for updates. Your workflow must also have a semantic version - number. Please see the :ref:`User Manual ` and - `update API docs ` for more information. - :type update_settings: :class:`dict` - :param input_encoding: encoding of command line arguments. You - should probably leave this as the default (``utf-8``), which - is the encoding Alfred uses. - :type input_encoding: :class:`unicode` - :param normalization: normalisation to apply to CLI args. - See :meth:`Workflow.decode` for more details. - :type normalization: :class:`unicode` - :param capture_args: Capture and act on ``workflow:*`` arguments. See - :ref:`Magic arguments ` for details. - :type capture_args: :class:`Boolean` - :param libraries: sequence of paths to directories containing - libraries. These paths will be prepended to ``sys.path``. - :type libraries: :class:`tuple` or :class:`list` - :param help_url: URL to webpage where a user can ask for help with - the workflow, report bugs, etc. This could be the GitHub repo - or a page on AlfredForum.com. If your workflow throws an error, - this URL will be displayed in the log and Alfred's debugger. It can - also be opened directly in a web browser with the ``workflow:help`` - :ref:`magic argument `. - :type help_url: :class:`unicode` or :class:`str` - - """ - - # Which class to use to generate feedback items. You probably - # won't want to change this - item_class = Item - - def __init__(self, default_settings=None, update_settings=None, - input_encoding='utf-8', normalization='NFC', - capture_args=True, libraries=None, - help_url=None): - """Create new :class:`Workflow` object.""" - self._default_settings = default_settings or {} - self._update_settings = update_settings or {} - self._input_encoding = input_encoding - self._normalizsation = normalization - self._capture_args = capture_args - self.help_url = help_url - self._workflowdir = None - self._settings_path = None - self._settings = None - self._bundleid = None - self._debugging = None - self._name = None - self._cache_serializer = 'cpickle' - self._data_serializer = 'cpickle' - self._info = None - self._info_loaded = False - self._logger = None - self._items = [] - self._alfred_env = None - # Version number of the workflow - self._version = UNSET - # Version from last workflow run - self._last_version_run = UNSET - # Cache for regex patterns created for filter keys - self._search_pattern_cache = {} - # Magic arguments - #: The prefix for all magic arguments. Default is ``workflow:`` - self.magic_prefix = 'workflow:' - #: Mapping of available magic arguments. The built-in magic - #: arguments are registered by default. To add your own magic arguments - #: (or override built-ins), add a key:value pair where the key is - #: what the user should enter (prefixed with :attr:`magic_prefix`) - #: and the value is a callable that will be called when the argument - #: is entered. If you would like to display a message in Alfred, the - #: function should return a ``unicode`` string. - #: - #: By default, the magic arguments documented - #: :ref:`here ` are registered. - self.magic_arguments = {} - - self._register_default_magic() - - if libraries: - sys.path = libraries + sys.path - - #################################################################### - # API methods - #################################################################### - - # info.plist contents and alfred_* environment variables ---------- - - @property - def alfred_version(self): - """Alfred version as :class:`~workflow.update.Version` object.""" - from .update import Version - return Version(self.alfred_env.get('version')) - - @property - def alfred_env(self): - """Dict of Alfred's environmental variables minus ``alfred_`` prefix. - - .. versionadded:: 1.7 - - The variables Alfred 2.4+ exports are: - - ============================ ========================================= - Variable Description - ============================ ========================================= - debug Set to ``1`` if Alfred's debugger is - open, otherwise unset. - preferences Path to Alfred.alfredpreferences - (where your workflows and settings are - stored). - preferences_localhash Machine-specific preferences are stored - in ``Alfred.alfredpreferences/preferences/local/`` - (see ``preferences`` above for - the path to ``Alfred.alfredpreferences``) - theme ID of selected theme - theme_background Background colour of selected theme in - format ``rgba(r,g,b,a)`` - theme_subtext Show result subtext. - ``0`` = Always, - ``1`` = Alternative actions only, - ``2`` = Selected result only, - ``3`` = Never - version Alfred version number, e.g. ``'2.4'`` - version_build Alfred build number, e.g. ``277`` - workflow_bundleid Bundle ID, e.g. - ``net.deanishe.alfred-mailto`` - workflow_cache Path to workflow's cache directory - workflow_data Path to workflow's data directory - workflow_name Name of current workflow - workflow_uid UID of workflow - workflow_version The version number specified in the - workflow configuration sheet/info.plist - ============================ ========================================= - - **Note:** all values are Unicode strings except ``version_build`` and - ``theme_subtext``, which are integers. - - :returns: ``dict`` of Alfred's environmental variables without the - ``alfred_`` prefix, e.g. ``preferences``, ``workflow_data``. - - """ - if self._alfred_env is not None: - return self._alfred_env - - data = {} - - for key in ( - 'alfred_debug', - 'alfred_preferences', - 'alfred_preferences_localhash', - 'alfred_theme', - 'alfred_theme_background', - 'alfred_theme_subtext', - 'alfred_version', - 'alfred_version_build', - 'alfred_workflow_bundleid', - 'alfred_workflow_cache', - 'alfred_workflow_data', - 'alfred_workflow_name', - 'alfred_workflow_uid', - 'alfred_workflow_version'): - - value = os.getenv(key) - - if isinstance(value, str): - if key in ('alfred_debug', 'alfred_version_build', - 'alfred_theme_subtext'): - value = int(value) - else: - value = self.decode(value) - - data[key[7:]] = value - - self._alfred_env = data - - return self._alfred_env - - @property - def info(self): - """:class:`dict` of ``info.plist`` contents.""" - if not self._info_loaded: - self._load_info_plist() - return self._info - - @property - def bundleid(self): - """Workflow bundle ID from environmental vars or ``info.plist``. - - :returns: bundle ID - :rtype: ``unicode`` - - """ - if not self._bundleid: - if self.alfred_env.get('workflow_bundleid'): - self._bundleid = self.alfred_env.get('workflow_bundleid') - else: - self._bundleid = self.info['bundleid'] - - return self._bundleid - - @property - def debugging(self): - """Whether Alfred's debugger is open. - - :returns: ``True`` if Alfred's debugger is open. - :rtype: ``bool`` - - """ - if self._debugging is None: - if self.alfred_env.get('debug') == 1: - self._debugging = True - else: - self._debugging = False - return self._debugging - - @property - def name(self): - """Workflow name from Alfred's environmental vars or ``info.plist``. - - :returns: workflow name - :rtype: ``unicode`` - - """ - if not self._name: - if self.alfred_env.get('workflow_name'): - self._name = self.decode(self.alfred_env.get('workflow_name')) - else: - self._name = self.decode(self.info['name']) - - return self._name - - @property - def version(self): - """Return the version of the workflow. - - .. versionadded:: 1.9.10 - - Get the workflow version from environment variable, - the ``update_settings`` dict passed on - instantiation, the ``version`` file located in the workflow's - root directory or ``info.plist``. Return ``None`` if none - exists or :class:`ValueError` if the version number is invalid - (i.e. not semantic). - - :returns: Version of the workflow (not Alfred-Workflow) - :rtype: :class:`~workflow.update.Version` object - - """ - if self._version is UNSET: - - version = None - # environment variable has priority - if self.alfred_env.get('workflow_version'): - version = self.alfred_env['workflow_version'] - - # Try `update_settings` - elif self._update_settings: - version = self._update_settings.get('version') - - # `version` file - if not version: - filepath = self.workflowfile('version') - - if os.path.exists(filepath): - with open(filepath, 'r') as f: - version = f.read() - - # info.plist - if not version: - version = self.info.get('version') - - if version: - from .update import Version - version = Version(version) - - self._version = version - - return self._version - - # Workflow utility methods ----------------------------------------- - - @property - def args(self): - """Return command line args as normalised unicode. - - Args are decoded and normalised via :meth:`~Workflow.decode`. - - The encoding and normalisation are the ``input_encoding`` and - ``normalization`` arguments passed to :class:`Workflow` (``UTF-8`` - and ``NFC`` are the defaults). - - If :class:`Workflow` is called with ``capture_args=True`` - (the default), :class:`Workflow` will look for certain - ``workflow:*`` args and, if found, perform the corresponding - actions and exit the workflow. - - See :ref:`Magic arguments ` for details. - - """ - msg = None - args = [self.decode(arg) for arg in sys.argv[1:]] - - # Handle magic args - if len(args) and self._capture_args: - for name in self.magic_arguments: - key = '{0}{1}'.format(self.magic_prefix, name) - if key in args: - msg = self.magic_arguments[name]() - - if msg: - self.logger.debug(msg) - if not sys.stdout.isatty(): # Show message in Alfred - self.add_item(msg, valid=False, icon=ICON_INFO) - self.send_feedback() - sys.exit(0) - return args - - @property - def cachedir(self): - """Path to workflow's cache directory. - - The cache directory is a subdirectory of Alfred's own cache directory - in ``~/Library/Caches``. The full path is: - - ``~/Library/Caches/com.runningwithcrayons.Alfred-X/Workflow Data/`` - - ``Alfred-X`` may be ``Alfred-2`` or ``Alfred-3``. - - :returns: full path to workflow's cache directory - :rtype: ``unicode`` - - """ - if self.alfred_env.get('workflow_cache'): - dirpath = self.alfred_env.get('workflow_cache') - - else: - dirpath = self._default_cachedir - - return self._create(dirpath) - - @property - def _default_cachedir(self): - """Alfred 2's default cache directory.""" - return os.path.join( - os.path.expanduser( - '~/Library/Caches/com.runningwithcrayons.Alfred-2/' - 'Workflow Data/'), - self.bundleid) - - @property - def datadir(self): - """Path to workflow's data directory. - - The data directory is a subdirectory of Alfred's own data directory in - ``~/Library/Application Support``. The full path is: - - ``~/Library/Application Support/Alfred 2/Workflow Data/`` - - :returns: full path to workflow data directory - :rtype: ``unicode`` - - """ - if self.alfred_env.get('workflow_data'): - dirpath = self.alfred_env.get('workflow_data') - - else: - dirpath = self._default_datadir - - return self._create(dirpath) - - @property - def _default_datadir(self): - """Alfred 2's default data directory.""" - return os.path.join(os.path.expanduser( - '~/Library/Application Support/Alfred 2/Workflow Data/'), - self.bundleid) - - @property - def workflowdir(self): - """Path to workflow's root directory (where ``info.plist`` is). - - :returns: full path to workflow root directory - :rtype: ``unicode`` - - """ - if not self._workflowdir: - # Try the working directory first, then the directory - # the library is in. CWD will be the workflow root if - # a workflow is being run in Alfred - candidates = [ - os.path.abspath(os.getcwd()), - os.path.dirname(os.path.abspath(os.path.dirname(__file__)))] - - # climb the directory tree until we find `info.plist` - for dirpath in candidates: - - # Ensure directory path is Unicode - dirpath = self.decode(dirpath) - - while True: - if os.path.exists(os.path.join(dirpath, 'info.plist')): - self._workflowdir = dirpath - break - - elif dirpath == '/': - # no `info.plist` found - break - - # Check the parent directory - dirpath = os.path.dirname(dirpath) - - # No need to check other candidates - if self._workflowdir: - break - - if not self._workflowdir: - raise IOError("'info.plist' not found in directory tree") - - return self._workflowdir - - def cachefile(self, filename): - """Path to ``filename`` in workflow's cache directory. - - Return absolute path to ``filename`` within your workflow's - :attr:`cache directory `. - - :param filename: basename of file - :type filename: ``unicode`` - :returns: full path to file within cache directory - :rtype: ``unicode`` - - """ - return os.path.join(self.cachedir, filename) - - def datafile(self, filename): - """Path to ``filename`` in workflow's data directory. - - Return absolute path to ``filename`` within your workflow's - :attr:`data directory `. - - :param filename: basename of file - :type filename: ``unicode`` - :returns: full path to file within data directory - :rtype: ``unicode`` - - """ - return os.path.join(self.datadir, filename) - - def workflowfile(self, filename): - """Return full path to ``filename`` in workflow's root directory. - - :param filename: basename of file - :type filename: ``unicode`` - :returns: full path to file within data directory - :rtype: ``unicode`` - - """ - return os.path.join(self.workflowdir, filename) - - @property - def logfile(self): - """Path to logfile. - - :returns: path to logfile within workflow's cache directory - :rtype: ``unicode`` - - """ - return self.cachefile('%s.log' % self.bundleid) - - @property - def logger(self): - """Logger that logs to both console and a log file. - - If Alfred's debugger is open, log level will be ``DEBUG``, - else it will be ``INFO``. - - Use :meth:`open_log` to open the log file in Console. - - :returns: an initialised :class:`~logging.Logger` - - """ - if self._logger: - return self._logger - - # Initialise new logger and optionally handlers - logger = logging.getLogger('') - - # Only add one set of handlers - # Exclude from coverage, as pytest will have configured the - # root logger already - if not len(logger.handlers): # pragma: no cover - - fmt = logging.Formatter( - '%(asctime)s %(filename)s:%(lineno)s' - ' %(levelname)-8s %(message)s', - datefmt='%H:%M:%S') - - logfile = logging.handlers.RotatingFileHandler( - self.logfile, - maxBytes=1024 * 1024, - backupCount=1) - logfile.setFormatter(fmt) - logger.addHandler(logfile) - - console = logging.StreamHandler() - console.setFormatter(fmt) - logger.addHandler(console) - - if self.debugging: - logger.setLevel(logging.DEBUG) - else: - logger.setLevel(logging.INFO) - - self._logger = logger - - return self._logger - - @logger.setter - def logger(self, logger): - """Set a custom logger. - - :param logger: The logger to use - :type logger: `~logging.Logger` instance - - """ - self._logger = logger - - @property - def settings_path(self): - """Path to settings file within workflow's data directory. - - :returns: path to ``settings.json`` file - :rtype: ``unicode`` - - """ - if not self._settings_path: - self._settings_path = self.datafile('settings.json') - return self._settings_path - - @property - def settings(self): - """Return a dictionary subclass that saves itself when changed. - - See :ref:`guide-settings` in the :ref:`user-manual` for more - information on how to use :attr:`settings` and **important - limitations** on what it can do. - - :returns: :class:`~workflow.workflow.Settings` instance - initialised from the data in JSON file at - :attr:`settings_path` or if that doesn't exist, with the - ``default_settings`` :class:`dict` passed to - :class:`Workflow` on instantiation. - :rtype: :class:`~workflow.workflow.Settings` instance - - """ - if not self._settings: - self.logger.debug('reading settings from %s', self.settings_path) - self._settings = Settings(self.settings_path, - self._default_settings) - return self._settings - - @property - def cache_serializer(self): - """Name of default cache serializer. - - .. versionadded:: 1.8 - - This serializer is used by :meth:`cache_data()` and - :meth:`cached_data()` - - See :class:`SerializerManager` for details. - - :returns: serializer name - :rtype: ``unicode`` - - """ - return self._cache_serializer - - @cache_serializer.setter - def cache_serializer(self, serializer_name): - """Set the default cache serialization format. - - .. versionadded:: 1.8 - - This serializer is used by :meth:`cache_data()` and - :meth:`cached_data()` - - The specified serializer must already by registered with the - :class:`SerializerManager` at `~workflow.workflow.manager`, - otherwise a :class:`ValueError` will be raised. - - :param serializer_name: Name of default serializer to use. - :type serializer_name: - - """ - if manager.serializer(serializer_name) is None: - raise ValueError( - 'Unknown serializer : `{0}`. Register your serializer ' - 'with `manager` first.'.format(serializer_name)) - - self.logger.debug('default cache serializer: %s', serializer_name) - - self._cache_serializer = serializer_name - - @property - def data_serializer(self): - """Name of default data serializer. - - .. versionadded:: 1.8 - - This serializer is used by :meth:`store_data()` and - :meth:`stored_data()` - - See :class:`SerializerManager` for details. - - :returns: serializer name - :rtype: ``unicode`` - - """ - return self._data_serializer - - @data_serializer.setter - def data_serializer(self, serializer_name): - """Set the default cache serialization format. - - .. versionadded:: 1.8 - - This serializer is used by :meth:`store_data()` and - :meth:`stored_data()` - - The specified serializer must already by registered with the - :class:`SerializerManager` at `~workflow.workflow.manager`, - otherwise a :class:`ValueError` will be raised. - - :param serializer_name: Name of serializer to use by default. - - """ - if manager.serializer(serializer_name) is None: - raise ValueError( - 'Unknown serializer : `{0}`. Register your serializer ' - 'with `manager` first.'.format(serializer_name)) - - self.logger.debug('default data serializer: %s', serializer_name) - - self._data_serializer = serializer_name - - def stored_data(self, name): - """Retrieve data from data directory. - - Returns ``None`` if there are no data stored under ``name``. - - .. versionadded:: 1.8 - - :param name: name of datastore - - """ - metadata_path = self.datafile('.{0}.alfred-workflow'.format(name)) - - if not os.path.exists(metadata_path): - self.logger.debug('no data stored for `%s`', name) - return None - - with open(metadata_path, 'rb') as file_obj: - serializer_name = file_obj.read().strip() - - serializer = manager.serializer(serializer_name) - - if serializer is None: - raise ValueError( - 'Unknown serializer `{0}`. Register a corresponding ' - 'serializer with `manager.register()` ' - 'to load this data.'.format(serializer_name)) - - self.logger.debug('data `%s` stored as `%s`', name, serializer_name) - - filename = '{0}.{1}'.format(name, serializer_name) - data_path = self.datafile(filename) - - if not os.path.exists(data_path): - self.logger.debug('no data stored: %s', name) - if os.path.exists(metadata_path): - os.unlink(metadata_path) - - return None - - with open(data_path, 'rb') as file_obj: - data = serializer.load(file_obj) - - self.logger.debug('stored data loaded: %s', data_path) - - return data - - def store_data(self, name, data, serializer=None): - """Save data to data directory. - - .. versionadded:: 1.8 - - If ``data`` is ``None``, the datastore will be deleted. - - Note that the datastore does NOT support mutliple threads. - - :param name: name of datastore - :param data: object(s) to store. **Note:** some serializers - can only handled certain types of data. - :param serializer: name of serializer to use. If no serializer - is specified, the default will be used. See - :class:`SerializerManager` for more information. - :returns: data in datastore or ``None`` - - """ - - # Ensure deletion is not interrupted by SIGTERM - @uninterruptible - def delete_paths(paths): - """Clear one or more data stores""" - for path in paths: - if os.path.exists(path): - os.unlink(path) - self.logger.debug('deleted data file: %s', path) - - serializer_name = serializer or self.data_serializer - - # In order for `stored_data()` to be able to load data stored with - # an arbitrary serializer, yet still have meaningful file extensions, - # the format (i.e. extension) is saved to an accompanying file - metadata_path = self.datafile('.{0}.alfred-workflow'.format(name)) - filename = '{0}.{1}'.format(name, serializer_name) - data_path = self.datafile(filename) - - if data_path == self.settings_path: - raise ValueError( - 'Cannot save data to' + - '`{0}` with format `{1}`. '.format(name, serializer_name) + - "This would overwrite Alfred-Workflow's settings file.") - - serializer = manager.serializer(serializer_name) - - if serializer is None: - raise ValueError( - 'Invalid serializer `{0}`. Register your serializer with ' - '`manager.register()` first.'.format(serializer_name)) - - if data is None: # Delete cached data - delete_paths((metadata_path, data_path)) - return - - # Ensure write is not interrupted by SIGTERM - @uninterruptible - def _store(): - # Save file extension - with atomic_writer(metadata_path, 'wb') as file_obj: - file_obj.write(serializer_name) - - with atomic_writer(data_path, 'wb') as file_obj: - serializer.dump(data, file_obj) - - _store() - - self.logger.debug('saved data: %s', data_path) - - def cached_data(self, name, data_func=None, max_age=60): - """Return cached data if younger than ``max_age`` seconds. - - Retrieve data from cache or re-generate and re-cache data if - stale/non-existant. If ``max_age`` is 0, return cached data no - matter how old. - - :param name: name of datastore - :param data_func: function to (re-)generate data. - :type data_func: ``callable`` - :param max_age: maximum age of cached data in seconds - :type max_age: ``int`` - :returns: cached data, return value of ``data_func`` or ``None`` - if ``data_func`` is not set - - """ - serializer = manager.serializer(self.cache_serializer) - - cache_path = self.cachefile('%s.%s' % (name, self.cache_serializer)) - age = self.cached_data_age(name) - - if (age < max_age or max_age == 0) and os.path.exists(cache_path): - with open(cache_path, 'rb') as file_obj: - self.logger.debug('loading cached data: %s', cache_path) - return serializer.load(file_obj) - - if not data_func: - return None - - data = data_func() - self.cache_data(name, data) - - return data - - def cache_data(self, name, data): - """Save ``data`` to cache under ``name``. - - If ``data`` is ``None``, the corresponding cache file will be - deleted. - - :param name: name of datastore - :param data: data to store. This may be any object supported by - the cache serializer - - """ - serializer = manager.serializer(self.cache_serializer) - - cache_path = self.cachefile('%s.%s' % (name, self.cache_serializer)) - - if data is None: - if os.path.exists(cache_path): - os.unlink(cache_path) - self.logger.debug('deleted cache file: %s', cache_path) - return - - with atomic_writer(cache_path, 'wb') as file_obj: - serializer.dump(data, file_obj) - - self.logger.debug('cached data: %s', cache_path) - - def cached_data_fresh(self, name, max_age): - """Whether cache `name` is less than `max_age` seconds old. - - :param name: name of datastore - :param max_age: maximum age of data in seconds - :type max_age: ``int`` - :returns: ``True`` if data is less than ``max_age`` old, else - ``False`` - - """ - age = self.cached_data_age(name) - - if not age: - return False - - return age < max_age - - def cached_data_age(self, name): - """Return age in seconds of cache `name` or 0 if cache doesn't exist. - - :param name: name of datastore - :type name: ``unicode`` - :returns: age of datastore in seconds - :rtype: ``int`` - - """ - cache_path = self.cachefile('%s.%s' % (name, self.cache_serializer)) - - if not os.path.exists(cache_path): - return 0 - - return time.time() - os.stat(cache_path).st_mtime - - def filter(self, query, items, key=lambda x: x, ascending=False, - include_score=False, min_score=0, max_results=0, - match_on=MATCH_ALL, fold_diacritics=True): - """Fuzzy search filter. Returns list of ``items`` that match ``query``. - - ``query`` is case-insensitive. Any item that does not contain the - entirety of ``query`` is rejected. - - If ``query`` is an empty string or contains only whitespace, - all items will match. - - :param query: query to test items against - :type query: ``unicode`` - :param items: iterable of items to test - :type items: ``list`` or ``tuple`` - :param key: function to get comparison key from ``items``. - Must return a ``unicode`` string. The default simply returns - the item. - :type key: ``callable`` - :param ascending: set to ``True`` to get worst matches first - :type ascending: ``Boolean`` - :param include_score: Useful for debugging the scoring algorithm. - If ``True``, results will be a list of tuples - ``(item, score, rule)``. - :type include_score: ``Boolean`` - :param min_score: If non-zero, ignore results with a score lower - than this. - :type min_score: ``int`` - :param max_results: If non-zero, prune results list to this length. - :type max_results: ``int`` - :param match_on: Filter option flags. Bitwise-combined list of - ``MATCH_*`` constants (see below). - :type match_on: ``int`` - :param fold_diacritics: Convert search keys to ASCII-only - characters if ``query`` only contains ASCII characters. - :type fold_diacritics: ``Boolean`` - :returns: list of ``items`` matching ``query`` or list of - ``(item, score, rule)`` `tuples` if ``include_score`` is ``True``. - ``rule`` is the ``MATCH_*`` rule that matched the item. - :rtype: ``list`` - - **Matching rules** - - By default, :meth:`filter` uses all of the following flags (i.e. - :const:`MATCH_ALL`). The tests are always run in the given order: - - 1. :const:`MATCH_STARTSWITH` - Item search key starts with ``query`` (case-insensitive). - 2. :const:`MATCH_CAPITALS` - The list of capital letters in item search key starts with - ``query`` (``query`` may be lower-case). E.g., ``of`` - would match ``OmniFocus``, ``gc`` would match ``Google Chrome``. - 3. :const:`MATCH_ATOM` - Search key is split into "atoms" on non-word characters - (.,-,' etc.). Matches if ``query`` is one of these atoms - (case-insensitive). - 4. :const:`MATCH_INITIALS_STARTSWITH` - Initials are the first characters of the above-described - "atoms" (case-insensitive). - 5. :const:`MATCH_INITIALS_CONTAIN` - ``query`` is a substring of the above-described initials. - 6. :const:`MATCH_INITIALS` - Combination of (4) and (5). - 7. :const:`MATCH_SUBSTRING` - ``query`` is a substring of item search key (case-insensitive). - 8. :const:`MATCH_ALLCHARS` - All characters in ``query`` appear in item search key in - the same order (case-insensitive). - 9. :const:`MATCH_ALL` - Combination of all the above. - - - :const:`MATCH_ALLCHARS` is considerably slower than the other - tests and provides much less accurate results. - - **Examples:** - - To ignore :const:`MATCH_ALLCHARS` (tends to provide the worst - matches and is expensive to run), use - ``match_on=MATCH_ALL ^ MATCH_ALLCHARS``. - - To match only on capitals, use ``match_on=MATCH_CAPITALS``. - - To match only on startswith and substring, use - ``match_on=MATCH_STARTSWITH | MATCH_SUBSTRING``. - - **Diacritic folding** - - .. versionadded:: 1.3 - - If ``fold_diacritics`` is ``True`` (the default), and ``query`` - contains only ASCII characters, non-ASCII characters in search keys - will be converted to ASCII equivalents (e.g. **ü** -> **u**, - **ß** -> **ss**, **é** -> **e**). - - See :const:`ASCII_REPLACEMENTS` for all replacements. - - If ``query`` contains non-ASCII characters, search keys will not be - altered. - - """ - if not query: - return items - - # Remove preceding/trailing spaces - query = query.strip() - - if not query: - return items - - # Use user override if there is one - fold_diacritics = self.settings.get('__workflow_diacritic_folding', - fold_diacritics) - - results = [] - - for item in items: - skip = False - score = 0 - words = [s.strip() for s in query.split(' ')] - value = key(item).strip() - if value == '': - continue - for word in words: - if word == '': - continue - s, rule = self._filter_item(value, word, match_on, - fold_diacritics) - - if not s: # Skip items that don't match part of the query - skip = True - score += s - - if skip: - continue - - if score: - # use "reversed" `score` (i.e. highest becomes lowest) and - # `value` as sort key. This means items with the same score - # will be sorted in alphabetical not reverse alphabetical order - results.append(((100.0 / score, value.lower(), score), - (item, score, rule))) - - # sort on keys, then discard the keys - results.sort(reverse=ascending) - results = [t[1] for t in results] - - if min_score: - results = [r for r in results if r[1] > min_score] - - if max_results and len(results) > max_results: - results = results[:max_results] - - # return list of ``(item, score, rule)`` - if include_score: - return results - # just return list of items - return [t[0] for t in results] - - def _filter_item(self, value, query, match_on, fold_diacritics): - """Filter ``value`` against ``query`` using rules ``match_on``. - - :returns: ``(score, rule)`` - - """ - query = query.lower() - - if not isascii(query): - fold_diacritics = False - - if fold_diacritics: - value = self.fold_to_ascii(value) - - # pre-filter any items that do not contain all characters - # of ``query`` to save on running several more expensive tests - if not set(query) <= set(value.lower()): - return (0, None) - - # item starts with query - if match_on & MATCH_STARTSWITH and value.lower().startswith(query): - score = 100.0 - (len(value) / len(query)) - - return (score, MATCH_STARTSWITH) - - # query matches capitalised letters in item, - # e.g. of = OmniFocus - if match_on & MATCH_CAPITALS: - initials = ''.join([c for c in value if c in INITIALS]) - if initials.lower().startswith(query): - score = 100.0 - (len(initials) / len(query)) - - return (score, MATCH_CAPITALS) - - # split the item into "atoms", i.e. words separated by - # spaces or other non-word characters - if (match_on & MATCH_ATOM or - match_on & MATCH_INITIALS_CONTAIN or - match_on & MATCH_INITIALS_STARTSWITH): - atoms = [s.lower() for s in split_on_delimiters(value)] - # print('atoms : %s --> %s' % (value, atoms)) - # initials of the atoms - initials = ''.join([s[0] for s in atoms if s]) - - if match_on & MATCH_ATOM: - # is `query` one of the atoms in item? - # similar to substring, but scores more highly, as it's - # a word within the item - if query in atoms: - score = 100.0 - (len(value) / len(query)) - - return (score, MATCH_ATOM) - - # `query` matches start (or all) of the initials of the - # atoms, e.g. ``himym`` matches "How I Met Your Mother" - # *and* "how i met your mother" (the ``capitals`` rule only - # matches the former) - if (match_on & MATCH_INITIALS_STARTSWITH and - initials.startswith(query)): - score = 100.0 - (len(initials) / len(query)) - - return (score, MATCH_INITIALS_STARTSWITH) - - # `query` is a substring of initials, e.g. ``doh`` matches - # "The Dukes of Hazzard" - elif (match_on & MATCH_INITIALS_CONTAIN and - query in initials): - score = 95.0 - (len(initials) / len(query)) - - return (score, MATCH_INITIALS_CONTAIN) - - # `query` is a substring of item - if match_on & MATCH_SUBSTRING and query in value.lower(): - score = 90.0 - (len(value) / len(query)) - - return (score, MATCH_SUBSTRING) - - # finally, assign a score based on how close together the - # characters in `query` are in item. - if match_on & MATCH_ALLCHARS: - search = self._search_for_query(query) - match = search(value) - if match: - score = 100.0 / ((1 + match.start()) * - (match.end() - match.start() + 1)) - - return (score, MATCH_ALLCHARS) - - # Nothing matched - return (0, None) - - def _search_for_query(self, query): - if query in self._search_pattern_cache: - return self._search_pattern_cache[query] - - # Build pattern: include all characters - pattern = [] - for c in query: - # pattern.append('[^{0}]*{0}'.format(re.escape(c))) - pattern.append('.*?{0}'.format(re.escape(c))) - pattern = ''.join(pattern) - search = re.compile(pattern, re.IGNORECASE).search - - self._search_pattern_cache[query] = search - return search - - def run(self, func, text_errors=False): - """Call ``func`` to run your workflow. - - :param func: Callable to call with ``self`` (i.e. the :class:`Workflow` - instance) as first argument. - :param text_errors: Emit error messages in plain text, not in - Alfred's XML/JSON feedback format. Use this when you're not - running Alfred-Workflow in a Script Filter and would like - to pass the error message to, say, a notification. - :type text_errors: ``Boolean`` - - ``func`` will be called with :class:`Workflow` instance as first - argument. - - ``func`` should be the main entry point to your workflow. - - Any exceptions raised will be logged and an error message will be - output to Alfred. - - """ - start = time.time() - - # Write to debugger to ensure "real" output starts on a new line - print('.', file=sys.stderr) - - # Call workflow's entry function/method within a try-except block - # to catch any errors and display an error message in Alfred - try: - if self.version: - self.logger.debug('---------- %s (%s) ----------', - self.name, self.version) - else: - self.logger.debug('---------- %s ----------', self.name) - - # Run update check if configured for self-updates. - # This call has to go in the `run` try-except block, as it will - # initialise `self.settings`, which will raise an exception - # if `settings.json` isn't valid. - # if self._update_settings: - # self.check_update() - - # Run workflow's entry function/method - func(self) - - # Set last version run to current version after a successful - # run - self.set_last_version() - - except Exception as err: - self.logger.exception(err) - if self.help_url: - self.logger.info('for assistance, see: %s', self.help_url) - - if not sys.stdout.isatty(): # Show error in Alfred - if text_errors: - print(err, end='') - else: - self._items = [] - if self._name: - name = self._name - elif self._bundleid: # pragma: no cover - name = self._bundleid - else: # pragma: no cover - name = os.path.dirname(__file__) - self.add_item("Error in workflow '%s'" % name, str(err), icon=ICON_ERROR) - self.send_feedback() - return 1 - - finally: - self.logger.debug('---------- finished in %0.3fs ----------', - time.time() - start) - - return 0 - - # Alfred feedback methods ------------------------------------------ - - def add_item(self, title, subtitle='', modifier_subtitles=None, arg=None, - autocomplete=None, valid=False, uid=None, icon=None, - icontype=None, type=None, largetext=None, copytext=None, - quicklookurl=None): - """Add an item to be output to Alfred. - - :param title: Title shown in Alfred - :type title: ``unicode`` - :param subtitle: Subtitle shown in Alfred - :type subtitle: ``unicode`` - :param modifier_subtitles: Subtitles shown when modifier - (CMD, OPT etc.) is pressed. Use a ``dict`` with the lowercase - keys ``cmd``, ``ctrl``, ``shift``, ``alt`` and ``fn`` - :type modifier_subtitles: ``dict`` - :param arg: Argument passed by Alfred as ``{query}`` when item is - actioned - :type arg: ``unicode`` - :param autocomplete: Text expanded in Alfred when item is TABbed - :type autocomplete: ``unicode`` - :param valid: Whether or not item can be actioned - :type valid: ``Boolean`` - :param uid: Used by Alfred to remember/sort items - :type uid: ``unicode`` - :param icon: Filename of icon to use - :type icon: ``unicode`` - :param icontype: Type of icon. Must be one of ``None`` , ``'filetype'`` - or ``'fileicon'``. Use ``'filetype'`` when ``icon`` is a filetype - such as ``'public.folder'``. Use ``'fileicon'`` when you wish to - use the icon of the file specified as ``icon``, e.g. - ``icon='/Applications/Safari.app', icontype='fileicon'``. - Leave as `None` if ``icon`` points to an actual - icon file. - :type icontype: ``unicode`` - :param type: Result type. Currently only ``'file'`` is supported - (by Alfred). This will tell Alfred to enable file actions for - this item. - :type type: ``unicode`` - :param largetext: Text to be displayed in Alfred's large text box - if user presses CMD+L on item. - :type largetext: ``unicode`` - :param copytext: Text to be copied to pasteboard if user presses - CMD+C on item. - :type copytext: ``unicode`` - :param quicklookurl: URL to be displayed using Alfred's Quick Look - feature (tapping ``SHIFT`` or ``⌘+Y`` on a result). - :type quicklookurl: ``unicode`` - :returns: :class:`Item` instance - - See :ref:`icons` for a list of the supported system icons. - - .. note:: - - Although this method returns an :class:`Item` instance, you don't - need to hold onto it or worry about it. All generated :class:`Item` - instances are also collected internally and sent to Alfred when - :meth:`send_feedback` is called. - - The generated :class:`Item` is only returned in case you want to - edit it or do something with it other than send it to Alfred. - - """ - item = self.item_class(title, subtitle, modifier_subtitles, arg, - autocomplete, valid, uid, icon, icontype, type, - largetext, copytext, quicklookurl) - self._items.append(item) - return item - - def send_feedback(self): - """Print stored items to console/Alfred as XML.""" - root = ET.Element('items') - for item in self._items: - root.append(item.elem) - sys.stdout.write('\n') - sys.stdout.write(ET.tostring(root).decode('utf-8')) - sys.stdout.flush() - - #################################################################### - # Updating methods - #################################################################### - - @property - def first_run(self): - """Return ``True`` if it's the first time this version has run. - - .. versionadded:: 1.9.10 - - Raises a :class:`ValueError` if :attr:`version` isn't set. - - """ - if not self.version: - raise ValueError('No workflow version set') - - if not self.last_version_run: - return True - - return self.version != self.last_version_run - - @property - def last_version_run(self): - """Return version of last version to run (or ``None``). - - .. versionadded:: 1.9.10 - - :returns: :class:`~workflow.update.Version` instance - or ``None`` - - """ - if self._last_version_run is UNSET: - - version = self.settings.get('__workflow_last_version') - if version: - from update import Version - version = Version(version) - - self._last_version_run = version - - self.logger.debug('last run version: %s', self._last_version_run) - - return self._last_version_run - - def set_last_version(self, version=None): - """Set :attr:`last_version_run` to current version. - - .. versionadded:: 1.9.10 - - :param version: version to store (default is current version) - :type version: :class:`~workflow.update.Version` instance - or ``unicode`` - :returns: ``True`` if version is saved, else ``False`` - - """ - if not version: - if not self.version: - self.logger.warning( - "Can't save last version: workflow has no version") - return False - - version = self.version - - if isinstance(version, str): - from update import Version - version = Version(version) - - self.settings['__workflow_last_version'] = str(version) - - self.logger.debug('set last run version: %s', version) - - return True - - @property - def update_available(self): - """Whether an update is available. - - .. versionadded:: 1.9 - - See :ref:`guide-updates` in the :ref:`user-manual` for detailed - information on how to enable your workflow to update itself. - - :returns: ``True`` if an update is available, else ``False`` - - """ - # Create a new workflow object to ensure standard serialiser - # is used (update.py is called without the user's settings) - update_data = Workflow().cached_data('__workflow_update_status', - max_age=0) - - self.logger.debug('update_data: %r', update_data) - - if not update_data or not update_data.get('available'): - return False - - return update_data['available'] - - @property - def prereleases(self): - """Whether workflow should update to pre-release versions. - - .. versionadded:: 1.16 - - :returns: ``True`` if pre-releases are enabled with the :ref:`magic - argument ` or the ``update_settings`` dict, else - ``False``. - - """ - if self._update_settings.get('prereleases'): - return True - - return self.settings.get('__workflow_prereleases') or False - - # def check_update(self, force=False): - # """Call update script if it's time to check for a new release. - - # .. versionadded:: 1.9 - - # The update script will be run in the background, so it won't - # interfere in the execution of your workflow. - - # See :ref:`guide-updates` in the :ref:`user-manual` for detailed - # information on how to enable your workflow to update itself. - - # :param force: Force update check - # :type force: ``Boolean`` - - # """ - # frequency = self._update_settings.get('frequency', - # DEFAULT_UPDATE_FREQUENCY) - - # if not force and not self.settings.get('__workflow_autoupdate', True): - # self.logger.debug('Auto update turned off by user') - # return - - # # Check for new version if it's time - # if (force or not self.cached_data_fresh( - # '__workflow_update_status', frequency * 86400)): - - # github_slug = self._update_settings['github_slug'] - # # version = self._update_settings['version'] - # version = str(self.version) - - # from background import run_in_background - - # # update.py is adjacent to this file - # update_script = os.path.join(os.path.dirname(__file__), - # b'update.py') - - # cmd = ['/usr/bin/python', update_script, 'check', github_slug, - # version] - - # if self.prereleases: - # cmd.append('--prereleases') - - # self.logger.info('checking for update ...') - - # run_in_background('__workflow_update_check', cmd) - - # else: - # self.logger.debug('update check not due') - - # def start_update(self): - # """Check for update and download and install new workflow file. - - # .. versionadded:: 1.9 - - # See :ref:`guide-updates` in the :ref:`user-manual` for detailed - # information on how to enable your workflow to update itself. - - # :returns: ``True`` if an update is available and will be - # installed, else ``False`` - - # """ - # import update - - # github_slug = self._update_settings['github_slug'] - # # version = self._update_settings['version'] - # version = str(self.version) - - # if not update.check_update(github_slug, version, self.prereleases): - # return False - - # from background import run_in_background - - # # update.py is adjacent to this file - # update_script = os.path.join(os.path.dirname(__file__), - # b'update.py') - - # cmd = ['/usr/bin/python', update_script, 'install', github_slug, - # version] - - # if self.prereleases: - # cmd.append('--prereleases') - - # self.logger.debug('downloading update ...') - # run_in_background('__workflow_update_install', cmd) - - # return True - - #################################################################### - # Keychain password storage methods - #################################################################### - - def save_password(self, account, password, service=None): - """Save account credentials. - - If the account exists, the old password will first be deleted - (Keychain throws an error otherwise). - - If something goes wrong, a :class:`KeychainError` exception will - be raised. - - :param account: name of the account the password is for, e.g. - "Pinboard" - :type account: ``unicode`` - :param password: the password to secure - :type password: ``unicode`` - :param service: Name of the service. By default, this is the - workflow's bundle ID - :type service: ``unicode`` - - """ - if not service: - service = self.bundleid - - try: - self._call_security('add-generic-password', service, account, - '-w', password) - self.logger.debug('saved password : %s:%s', service, account) - - except PasswordExists: - self.logger.debug('password exists : %s:%s', service, account) - current_password = self.get_password(account, service) - - if current_password == password: - self.logger.debug('password unchanged') - - else: - self.delete_password(account, service) - self._call_security('add-generic-password', service, - account, '-w', password) - self.logger.debug('save_password : %s:%s', service, account) - - def get_password(self, account, service=None): - """Retrieve the password saved at ``service/account``. - - Raise :class:`PasswordNotFound` exception if password doesn't exist. - - :param account: name of the account the password is for, e.g. - "Pinboard" - :type account: ``unicode`` - :param service: Name of the service. By default, this is the workflow's - bundle ID - :type service: ``unicode`` - :returns: account password - :rtype: ``unicode`` - - """ - if not service: - service = self.bundleid - - output = self._call_security('find-generic-password', service, - account, '-g') - - # Parsing of `security` output is adapted from python-keyring - # by Jason R. Coombs - # https://pypi.python.org/pypi/keyring - m = re.search( - r'password:\s*(?:0x(?P[0-9A-F]+)\s*)?(?:"(?P.*)")?', - output) - - if m: - groups = m.groupdict() - h = groups.get('hex') - password = groups.get('pw') - if h: - password = binascii.unhexlify(h) - - self.logger.debug('got password : %s:%s', service, account) - - return password - - def delete_password(self, account, service=None): - """Delete the password stored at ``service/account``. - - Raise :class:`PasswordNotFound` if account is unknown. - - :param account: name of the account the password is for, e.g. - "Pinboard" - :type account: ``unicode`` - :param service: Name of the service. By default, this is the workflow's - bundle ID - :type service: ``unicode`` - - """ - if not service: - service = self.bundleid - - self._call_security('delete-generic-password', service, account) - - self.logger.debug('deleted password : %s:%s', service, account) - - #################################################################### - # Methods for workflow:* magic args - #################################################################### - - def _register_default_magic(self): - """Register the built-in magic arguments.""" - - # TODO: refactor & simplify - # Wrap callback and message with callable - def callback(func, msg): - def wrapper(): - func() - return msg - - return wrapper - - self.magic_arguments['delcache'] = callback(self.clear_cache, - 'Deleted workflow cache') - self.magic_arguments['deldata'] = callback(self.clear_data, - 'Deleted workflow data') - self.magic_arguments['delsettings'] = callback( - self.clear_settings, 'Deleted workflow settings') - self.magic_arguments['reset'] = callback(self.reset, - 'Reset workflow') - self.magic_arguments['openlog'] = callback(self.open_log, - 'Opening workflow log file') - self.magic_arguments['opencache'] = callback( - self.open_cachedir, 'Opening workflow cache directory') - self.magic_arguments['opendata'] = callback( - self.open_datadir, 'Opening workflow data directory') - self.magic_arguments['openworkflow'] = callback( - self.open_workflowdir, 'Opening workflow directory') - self.magic_arguments['openterm'] = callback( - self.open_terminal, 'Opening workflow root directory in Terminal') - - # Diacritic folding - def fold_on(): - self.settings['__workflow_diacritic_folding'] = True - return 'Diacritics will always be folded' - - def fold_off(): - self.settings['__workflow_diacritic_folding'] = False - return 'Diacritics will never be folded' - - def fold_default(): - if '__workflow_diacritic_folding' in self.settings: - del self.settings['__workflow_diacritic_folding'] - return 'Diacritics folding reset' - - self.magic_arguments['foldingon'] = fold_on - self.magic_arguments['foldingoff'] = fold_off - self.magic_arguments['foldingdefault'] = fold_default - - # Updates - def update_on(): - self.settings['__workflow_autoupdate'] = True - return 'Auto update turned on' - - def update_off(): - self.settings['__workflow_autoupdate'] = False - return 'Auto update turned off' - - def prereleases_on(): - self.settings['__workflow_prereleases'] = True - return 'Prerelease updates turned on' - - def prereleases_off(): - self.settings['__workflow_prereleases'] = False - return 'Prerelease updates turned off' - - def do_update(): - if self.start_update(): - return 'Downloading and installing update ...' - else: - return 'No update available' - - self.magic_arguments['autoupdate'] = update_on - self.magic_arguments['noautoupdate'] = update_off - self.magic_arguments['prereleases'] = prereleases_on - self.magic_arguments['noprereleases'] = prereleases_off - self.magic_arguments['update'] = do_update - - # Help - def do_help(): - if self.help_url: - self.open_help() - return 'Opening workflow help URL in browser' - else: - return 'Workflow has no help URL' - - def show_version(): - if self.version: - return 'Version: {0}'.format(self.version) - else: - return 'This workflow has no version number' - - def list_magic(): - """Display all available magic args in Alfred.""" - isatty = sys.stderr.isatty() - for name in sorted(self.magic_arguments.keys()): - if name == 'magic': - continue - arg = self.magic_prefix + name - self.logger.debug(arg) - - if not isatty: - self.add_item(arg, icon=ICON_INFO) - - if not isatty: - self.send_feedback() - - self.magic_arguments['help'] = do_help - self.magic_arguments['magic'] = list_magic - self.magic_arguments['version'] = show_version - - def clear_cache(self, filter_func=lambda f: True): - """Delete all files in workflow's :attr:`cachedir`. - - :param filter_func: Callable to determine whether a file should be - deleted or not. ``filter_func`` is called with the filename - of each file in the data directory. If it returns ``True``, - the file will be deleted. - By default, *all* files will be deleted. - :type filter_func: ``callable`` - """ - self._delete_directory_contents(self.cachedir, filter_func) - - def clear_data(self, filter_func=lambda f: True): - """Delete all files in workflow's :attr:`datadir`. - - :param filter_func: Callable to determine whether a file should be - deleted or not. ``filter_func`` is called with the filename - of each file in the data directory. If it returns ``True``, - the file will be deleted. - By default, *all* files will be deleted. - :type filter_func: ``callable`` - """ - self._delete_directory_contents(self.datadir, filter_func) - - def clear_settings(self): - """Delete workflow's :attr:`settings_path`.""" - if os.path.exists(self.settings_path): - os.unlink(self.settings_path) - self.logger.debug('deleted : %r', self.settings_path) - - def reset(self): - """Delete workflow settings, cache and data. - - File :attr:`settings ` and directories - :attr:`cache ` and :attr:`data ` are deleted. - - """ - self.clear_cache() - self.clear_data() - self.clear_settings() - - def open_log(self): - """Open :attr:`logfile` in default app (usually Console.app).""" - subprocess.call(['open', self.logfile]) - - def open_cachedir(self): - """Open the workflow's :attr:`cachedir` in Finder.""" - subprocess.call(['open', self.cachedir]) - - def open_datadir(self): - """Open the workflow's :attr:`datadir` in Finder.""" - subprocess.call(['open', self.datadir]) - - def open_workflowdir(self): - """Open the workflow's :attr:`workflowdir` in Finder.""" - subprocess.call(['open', self.workflowdir]) - - def open_terminal(self): - """Open a Terminal window at workflow's :attr:`workflowdir`.""" - subprocess.call(['open', '-a', 'Terminal', - self.workflowdir]) - - def open_help(self): - """Open :attr:`help_url` in default browser.""" - subprocess.call(['open', self.help_url]) - - return 'Opening workflow help URL in browser' - - #################################################################### - # Helper methods - #################################################################### - - def decode(self, text, encoding=None, normalization=None): - """Return ``text`` as normalised unicode. - - If ``encoding`` and/or ``normalization`` is ``None``, the - ``input_encoding``and ``normalization`` parameters passed to - :class:`Workflow` are used. - - :param text: string - :type text: encoded or Unicode string. If ``text`` is already a - Unicode string, it will only be normalised. - :param encoding: The text encoding to use to decode ``text`` to - Unicode. - :type encoding: ``unicode`` or ``None`` - :param normalization: The nomalisation form to apply to ``text``. - :type normalization: ``unicode`` or ``None`` - :returns: decoded and normalised ``unicode`` - - :class:`Workflow` uses "NFC" normalisation by default. This is the - standard for Python and will work well with data from the web (via - :mod:`~workflow.web` or :mod:`json`). - - macOS, on the other hand, uses "NFD" normalisation (nearly), so data - coming from the system (e.g. via :mod:`subprocess` or - :func:`os.listdir`/:mod:`os.path`) may not match. You should either - normalise this data, too, or change the default normalisation used by - :class:`Workflow`. - - """ - encoding = encoding or self._input_encoding - normalization = normalization or self._normalizsation - if not isinstance(text, str): - text = str(text) - return unicodedata.normalize(normalization, text) - - def fold_to_ascii(self, text): - """Convert non-ASCII characters to closest ASCII equivalent. - - .. versionadded:: 1.3 - - .. note:: This only works for a subset of European languages. - - :param text: text to convert - :type text: ``unicode`` - :returns: text containing only ASCII characters - :rtype: ``unicode`` - - """ - if isascii(text): - return text - text = ''.join([ASCII_REPLACEMENTS.get(c, c) for c in text]) - return unicodedata.normalize('NFKD', text).encode('ascii', 'ignore') - - def dumbify_punctuation(self, text): - """Convert non-ASCII punctuation to closest ASCII equivalent. - - This method replaces "smart" quotes and n- or m-dashes with their - workaday ASCII equivalents. This method is currently not used - internally, but exists as a helper method for workflow authors. - - .. versionadded: 1.9.7 - - :param text: text to convert - :type text: ``unicode`` - :returns: text with only ASCII punctuation - :rtype: ``unicode`` - - """ - if isascii(text): - return text - - text = ''.join([DUMB_PUNCTUATION.get(c, c) for c in text]) - return text - - def _delete_directory_contents(self, dirpath, filter_func): - """Delete all files in a directory. - - :param dirpath: path to directory to clear - :type dirpath: ``unicode`` or ``str`` - :param filter_func function to determine whether a file shall be - deleted or not. - :type filter_func ``callable`` - - """ - if os.path.exists(dirpath): - for filename in os.listdir(dirpath): - if not filter_func(filename): - continue - path = os.path.join(dirpath, filename) - if os.path.isdir(path): - shutil.rmtree(path) - else: - os.unlink(path) - self.logger.debug('deleted : %r', path) - - def _load_info_plist(self): - """Load workflow info from ``info.plist``.""" - # info.plist should be in the directory above this one - with open(self.workflowfile('info.plist'), mode='rb') as f: - self._info = plistlib.load(f) - self._info_loaded = True - - def _create(self, dirpath): - """Create directory `dirpath` if it doesn't exist. - - :param dirpath: path to directory - :type dirpath: ``unicode`` - :returns: ``dirpath`` argument - :rtype: ``unicode`` - - """ - if not os.path.exists(dirpath): - os.makedirs(dirpath) - return dirpath - - def _call_security(self, action, service, account, *args): - """Call ``security`` CLI program that provides access to keychains. - - May raise `PasswordNotFound`, `PasswordExists` or `KeychainError` - exceptions (the first two are subclasses of `KeychainError`). - - :param action: The ``security`` action to call, e.g. - ``add-generic-password`` - :type action: ``unicode`` - :param service: Name of the service. - :type service: ``unicode`` - :param account: name of the account the password is for, e.g. - "Pinboard" - :type account: ``unicode`` - :param password: the password to secure - :type password: ``unicode`` - :param *args: list of command line arguments to be passed to - ``security`` - :type *args: `list` or `tuple` - :returns: ``(retcode, output)``. ``retcode`` is an `int`, ``output`` a - ``unicode`` string. - :rtype: `tuple` (`int`, ``unicode``) - - """ - cmd = ['security', action, '-s', service, '-a', account] + list(args) - p = subprocess.Popen(cmd, stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - stdout, _ = p.communicate() - if p.returncode == 44: # password does not exist - raise PasswordNotFound() - elif p.returncode == 45: # password already exists - raise PasswordExists() - elif p.returncode > 0: - err = KeychainError('Unknown Keychain error : %s' % stdout) - err.retcode = p.returncode - raise err - return stdout.strip().decode('utf-8') \ No newline at end of file diff --git a/src/lib/workflow_old/workflow3.py b/src/lib/workflow_old/workflow3.py deleted file mode 100644 index b92c4be..0000000 --- a/src/lib/workflow_old/workflow3.py +++ /dev/null @@ -1,721 +0,0 @@ -# encoding: utf-8 -# -# Copyright (c) 2016 Dean Jackson -# -# MIT Licence. See http://opensource.org/licenses/MIT -# -# Created on 2016-06-25 -# - -"""An Alfred 3+ version of :class:`~workflow.Workflow`. - -:class:`~workflow.Workflow3` supports new features, such as -setting :ref:`workflow-variables` and -:class:`the more advanced modifiers ` supported by Alfred 3+. - -In order for the feedback mechanism to work correctly, it's important -to create :class:`Item3` and :class:`Modifier` objects via the -:meth:`Workflow3.add_item()` and :meth:`Item3.add_modifier()` methods -respectively. If you instantiate :class:`Item3` or :class:`Modifier` -objects directly, the current :class:`Workflow3` object won't be aware -of them, and they won't be sent to Alfred when you call -:meth:`Workflow3.send_feedback()`. - -""" - -from __future__ import print_function, unicode_literals, absolute_import - -import json -import os -import sys - -from .workflow import ICON_WARNING, Workflow - - -class Variables(dict): - """Workflow variables for Run Script actions. - - .. versionadded: 1.26 - - This class allows you to set workflow variables from - Run Script actions. - - It is a subclass of :class:`dict`. - - >>> v = Variables(username='deanishe', password='hunter2') - >>> v.arg = u'output value' - >>> print(v) - - See :ref:`variables-run-script` in the User Guide for more - information. - - Args: - arg (unicode, optional): Main output/``{query}``. - **variables: Workflow variables to set. - - - Attributes: - arg (unicode): Output value (``{query}``). - config (dict): Configuration for downstream workflow element. - - """ - - def __init__(self, arg=None, **variables): - """Create a new `Variables` object.""" - self.arg = arg - self.config = {} - super(Variables, self).__init__(**variables) - - @property - def obj(self): - """Return ``alfredworkflow`` `dict`.""" - o = {} - if self: - d2 = {} - for k, v in self.items(): - d2[k] = v - o['variables'] = d2 - - if self.config: - o['config'] = self.config - - if self.arg is not None: - o['arg'] = self.arg - - return {'alfredworkflow': o} - - def __unicode__(self): - """Convert to ``alfredworkflow`` JSON object. - - Returns: - unicode: ``alfredworkflow`` JSON object - - """ - if not self and not self.config: - if self.arg: - return self.arg - else: - return u'' - - return json.dumps(self.obj) - - def __str__(self): - """Convert to ``alfredworkflow`` JSON object. - - Returns: - str: UTF-8 encoded ``alfredworkflow`` JSON object - - """ - return unicode(self).encode('utf-8') - - -class Modifier(object): - """Modify :class:`Item3` arg/icon/variables when modifier key is pressed. - - Don't use this class directly (as it won't be associated with any - :class:`Item3`), but rather use :meth:`Item3.add_modifier()` - to add modifiers to results. - - >>> it = wf.add_item('Title', 'Subtitle', valid=True) - >>> it.setvar('name', 'default') - >>> m = it.add_modifier('cmd') - >>> m.setvar('name', 'alternate') - - See :ref:`workflow-variables` in the User Guide for more information - and :ref:`example usage `. - - Args: - key (unicode): Modifier key, e.g. ``"cmd"``, ``"alt"`` etc. - subtitle (unicode, optional): Override default subtitle. - arg (unicode, optional): Argument to pass for this modifier. - valid (bool, optional): Override item's validity. - icon (unicode, optional): Filepath/UTI of icon to use - icontype (unicode, optional): Type of icon. See - :meth:`Workflow.add_item() ` - for valid values. - - Attributes: - arg (unicode): Arg to pass to following action. - config (dict): Configuration for a downstream element, such as - a File Filter. - icon (unicode): Filepath/UTI of icon. - icontype (unicode): Type of icon. See - :meth:`Workflow.add_item() ` - for valid values. - key (unicode): Modifier key (see above). - subtitle (unicode): Override item subtitle. - valid (bool): Override item validity. - variables (dict): Workflow variables set by this modifier. - - """ - - def __init__(self, key, subtitle=None, arg=None, valid=None, icon=None, - icontype=None): - """Create a new :class:`Modifier`. - - Don't use this class directly (as it won't be associated with any - :class:`Item3`), but rather use :meth:`Item3.add_modifier()` - to add modifiers to results. - - Args: - key (unicode): Modifier key, e.g. ``"cmd"``, ``"alt"`` etc. - subtitle (unicode, optional): Override default subtitle. - arg (unicode, optional): Argument to pass for this modifier. - valid (bool, optional): Override item's validity. - icon (unicode, optional): Filepath/UTI of icon to use - icontype (unicode, optional): Type of icon. See - :meth:`Workflow.add_item() ` - for valid values. - - """ - self.key = key - self.subtitle = subtitle - self.arg = arg - self.valid = valid - self.icon = icon - self.icontype = icontype - - self.config = {} - self.variables = {} - - def setvar(self, name, value): - """Set a workflow variable for this Item. - - Args: - name (unicode): Name of variable. - value (unicode): Value of variable. - - """ - self.variables[name] = value - - def getvar(self, name, default=None): - """Return value of workflow variable for ``name`` or ``default``. - - Args: - name (unicode): Variable name. - default (None, optional): Value to return if variable is unset. - - Returns: - unicode or ``default``: Value of variable if set or ``default``. - - """ - return self.variables.get(name, default) - - @property - def obj(self): - """Modifier formatted for JSON serialization for Alfred 3. - - Returns: - dict: Modifier for serializing to JSON. - - """ - o = {} - - if self.subtitle is not None: - o['subtitle'] = self.subtitle - - if self.arg is not None: - o['arg'] = self.arg - - if self.valid is not None: - o['valid'] = self.valid - - if self.variables: - o['variables'] = self.variables - - if self.config: - o['config'] = self.config - - icon = self._icon() - if icon: - o['icon'] = icon - - return o - - def _icon(self): - """Return `icon` object for item. - - Returns: - dict: Mapping for item `icon` (may be empty). - - """ - icon = {} - if self.icon is not None: - icon['path'] = self.icon - - if self.icontype is not None: - icon['type'] = self.icontype - - return icon - - -class Item3(object): - """Represents a feedback item for Alfred 3+. - - Generates Alfred-compliant JSON for a single item. - - Don't use this class directly (as it then won't be associated with - any :class:`Workflow3 ` object), but rather use - :meth:`Workflow3.add_item() `. - See :meth:`~workflow.Workflow3.add_item` for details of arguments. - - """ - - def __init__(self, title, subtitle='', arg=None, autocomplete=None, - match=None, valid=False, uid=None, icon=None, icontype=None, - type=None, largetext=None, copytext=None, quicklookurl=None): - """Create a new :class:`Item3` object. - - Use same arguments as for - :class:`Workflow.Item `. - - Argument ``subtitle_modifiers`` is not supported. - - """ - self.title = title - self.subtitle = subtitle - self.arg = arg - self.autocomplete = autocomplete - self.match = match - self.valid = valid - self.uid = uid - self.icon = icon - self.icontype = icontype - self.type = type - self.quicklookurl = quicklookurl - self.largetext = largetext - self.copytext = copytext - - self.modifiers = {} - - self.config = {} - self.variables = {} - - def setvar(self, name, value): - """Set a workflow variable for this Item. - - Args: - name (unicode): Name of variable. - value (unicode): Value of variable. - - """ - self.variables[name] = value - - def getvar(self, name, default=None): - """Return value of workflow variable for ``name`` or ``default``. - - Args: - name (unicode): Variable name. - default (None, optional): Value to return if variable is unset. - - Returns: - unicode or ``default``: Value of variable if set or ``default``. - - """ - return self.variables.get(name, default) - - def add_modifier(self, key, subtitle=None, arg=None, valid=None, icon=None, - icontype=None): - """Add alternative values for a modifier key. - - Args: - key (unicode): Modifier key, e.g. ``"cmd"`` or ``"alt"`` - subtitle (unicode, optional): Override item subtitle. - arg (unicode, optional): Input for following action. - valid (bool, optional): Override item validity. - icon (unicode, optional): Filepath/UTI of icon. - icontype (unicode, optional): Type of icon. See - :meth:`Workflow.add_item() ` - for valid values. - - Returns: - Modifier: Configured :class:`Modifier`. - - """ - mod = Modifier(key, subtitle, arg, valid, icon, icontype) - - # Add Item variables to Modifier - mod.variables.update(self.variables) - - self.modifiers[key] = mod - - return mod - - @property - def obj(self): - """Item formatted for JSON serialization. - - Returns: - dict: Data suitable for Alfred 3 feedback. - - """ - # Required values - o = { - 'title': self.title, - 'subtitle': self.subtitle, - 'valid': self.valid, - } - - # Optional values - if self.arg is not None: - o['arg'] = self.arg - - if self.autocomplete is not None: - o['autocomplete'] = self.autocomplete - - if self.match is not None: - o['match'] = self.match - - if self.uid is not None: - o['uid'] = self.uid - - if self.type is not None: - o['type'] = self.type - - if self.quicklookurl is not None: - o['quicklookurl'] = self.quicklookurl - - if self.variables: - o['variables'] = self.variables - - if self.config: - o['config'] = self.config - - # Largetype and copytext - text = self._text() - if text: - o['text'] = text - - icon = self._icon() - if icon: - o['icon'] = icon - - # Modifiers - mods = self._modifiers() - if mods: - o['mods'] = mods - - return o - - def _icon(self): - """Return `icon` object for item. - - Returns: - dict: Mapping for item `icon` (may be empty). - - """ - icon = {} - if self.icon is not None: - icon['path'] = self.icon - - if self.icontype is not None: - icon['type'] = self.icontype - - return icon - - def _text(self): - """Return `largetext` and `copytext` object for item. - - Returns: - dict: `text` mapping (may be empty) - - """ - text = {} - if self.largetext is not None: - text['largetype'] = self.largetext - - if self.copytext is not None: - text['copy'] = self.copytext - - return text - - def _modifiers(self): - """Build `mods` dictionary for JSON feedback. - - Returns: - dict: Modifier mapping or `None`. - - """ - if self.modifiers: - mods = {} - for k, mod in self.modifiers.items(): - mods[k] = mod.obj - - return mods - - return None - - -class Workflow3(Workflow): - """Workflow class that generates Alfred 3+ feedback. - - It is a subclass of :class:`~workflow.Workflow` and most of its - methods are documented there. - - Attributes: - item_class (class): Class used to generate feedback items. - variables (dict): Top level workflow variables. - - """ - - item_class = Item3 - - def __init__(self, **kwargs): - """Create a new :class:`Workflow3` object. - - See :class:`~workflow.Workflow` for documentation. - - """ - Workflow.__init__(self, **kwargs) - self.variables = {} - self._rerun = 0 - # Get session ID from environment if present - self._session_id = os.getenv('_WF_SESSION_ID') or None - if self._session_id: - self.setvar('_WF_SESSION_ID', self._session_id) - - @property - def _default_cachedir(self): - """Alfred 4's default cache directory.""" - return os.path.join( - os.path.expanduser( - '~/Library/Caches/com.runningwithcrayons.Alfred/' - 'Workflow Data/'), - self.bundleid) - - @property - def _default_datadir(self): - """Alfred 4's default data directory.""" - return os.path.join(os.path.expanduser( - '~/Library/Application Support/Alfred/Workflow Data/'), - self.bundleid) - - @property - def rerun(self): - """How often (in seconds) Alfred should re-run the Script Filter.""" - return self._rerun - - @rerun.setter - def rerun(self, seconds): - """Interval at which Alfred should re-run the Script Filter. - - Args: - seconds (int): Interval between runs. - """ - self._rerun = seconds - - @property - def session_id(self): - """A unique session ID every time the user uses the workflow. - - .. versionadded:: 1.25 - - The session ID persists while the user is using this workflow. - It expires when the user runs a different workflow or closes - Alfred. - - """ - if not self._session_id: - from uuid import uuid4 - self._session_id = uuid4().hex - self.setvar('_WF_SESSION_ID', self._session_id) - - return self._session_id - - def setvar(self, name, value, persist=False): - """Set a "global" workflow variable. - - .. versionchanged:: 1.33 - - These variables are always passed to downstream workflow objects. - - If you have set :attr:`rerun`, these variables are also passed - back to the script when Alfred runs it again. - - Args: - name (unicode): Name of variable. - value (unicode): Value of variable. - persist (bool, optional): Also save variable to ``info.plist``? - - """ - self.variables[name] = value - if persist: - from .util import set_config - set_config(name, value, self.bundleid) - self.logger.debug('saved variable %r with value %r to info.plist', - name, value) - - def getvar(self, name, default=None): - """Return value of workflow variable for ``name`` or ``default``. - - Args: - name (unicode): Variable name. - default (None, optional): Value to return if variable is unset. - - Returns: - unicode or ``default``: Value of variable if set or ``default``. - - """ - return self.variables.get(name, default) - - def add_item(self, title, subtitle='', arg=None, autocomplete=None, - valid=False, uid=None, icon=None, icontype=None, type=None, - largetext=None, copytext=None, quicklookurl=None, match=None): - """Add an item to be output to Alfred. - - Args: - match (unicode, optional): If you have "Alfred filters results" - turned on for your Script Filter, Alfred (version 3.5 and - above) will filter against this field, not ``title``. - - See :meth:`Workflow.add_item() ` for - the main documentation and other parameters. - - The key difference is that this method does not support the - ``modifier_subtitles`` argument. Use the :meth:`~Item3.add_modifier()` - method instead on the returned item instead. - - Returns: - Item3: Alfred feedback item. - - """ - item = self.item_class(title, subtitle, arg, autocomplete, - match, valid, uid, icon, icontype, type, - largetext, copytext, quicklookurl) - - # Add variables to child item - item.variables.update(self.variables) - - self._items.append(item) - return item - - @property - def _session_prefix(self): - """Filename prefix for current session.""" - return '_wfsess-{0}-'.format(self.session_id) - - def _mk_session_name(self, name): - """New cache name/key based on session ID.""" - return self._session_prefix + name - - def cache_data(self, name, data, session=False): - """Cache API with session-scoped expiry. - - .. versionadded:: 1.25 - - Args: - name (str): Cache key - data (object): Data to cache - session (bool, optional): Whether to scope the cache - to the current session. - - ``name`` and ``data`` are the same as for the - :meth:`~workflow.Workflow.cache_data` method on - :class:`~workflow.Workflow`. - - If ``session`` is ``True``, then ``name`` is prefixed - with :attr:`session_id`. - - """ - if session: - name = self._mk_session_name(name) - - return super(Workflow3, self).cache_data(name, data) - - def cached_data(self, name, data_func=None, max_age=60, session=False): - """Cache API with session-scoped expiry. - - .. versionadded:: 1.25 - - Args: - name (str): Cache key - data_func (callable): Callable that returns fresh data. It - is called if the cache has expired or doesn't exist. - max_age (int): Maximum allowable age of cache in seconds. - session (bool, optional): Whether to scope the cache - to the current session. - - ``name``, ``data_func`` and ``max_age`` are the same as for the - :meth:`~workflow.Workflow.cached_data` method on - :class:`~workflow.Workflow`. - - If ``session`` is ``True``, then ``name`` is prefixed - with :attr:`session_id`. - - """ - if session: - name = self._mk_session_name(name) - - return super(Workflow3, self).cached_data(name, data_func, max_age) - - def clear_session_cache(self, current=False): - """Remove session data from the cache. - - .. versionadded:: 1.25 - .. versionchanged:: 1.27 - - By default, data belonging to the current session won't be - deleted. Set ``current=True`` to also clear current session. - - Args: - current (bool, optional): If ``True``, also remove data for - current session. - - """ - def _is_session_file(filename): - if current: - return filename.startswith('_wfsess-') - return filename.startswith('_wfsess-') \ - and not filename.startswith(self._session_prefix) - - self.clear_cache(_is_session_file) - - @property - def obj(self): - """Feedback formatted for JSON serialization. - - Returns: - dict: Data suitable for Alfred 3 feedback. - - """ - items = [] - for item in self._items: - items.append(item.obj) - - o = {'items': items} - if self.variables: - o['variables'] = self.variables - if self.rerun: - o['rerun'] = self.rerun - return o - - def warn_empty(self, title, subtitle=u'', icon=None): - """Add a warning to feedback if there are no items. - - .. versionadded:: 1.31 - - Add a "warning" item to Alfred feedback if no other items - have been added. This is a handy shortcut to prevent Alfred - from showing its fallback searches, which is does if no - items are returned. - - Args: - title (unicode): Title of feedback item. - subtitle (unicode, optional): Subtitle of feedback item. - icon (str, optional): Icon for feedback item. If not - specified, ``ICON_WARNING`` is used. - - Returns: - Item3: Newly-created item. - - """ - if len(self._items): - return - - icon = icon or ICON_WARNING - return self.add_item(title, subtitle, icon=icon) - - def send_feedback(self): - """Print stored items to console/Alfred as JSON.""" - json.dump(self.obj, sys.stdout) - sys.stdout.flush() diff --git a/src/lib/workflow_old/workflow_old.py b/src/lib/workflow_old/workflow_old.py deleted file mode 100644 index 2a057b0..0000000 --- a/src/lib/workflow_old/workflow_old.py +++ /dev/null @@ -1,2821 +0,0 @@ -# encoding: utf-8 -# -# Copyright (c) 2014 Dean Jackson -# -# MIT Licence. See http://opensource.org/licenses/MIT -# -# Created on 2014-02-15 -# - -"""The :class:`Workflow` object is the main interface to this library. - -:class:`Workflow` is targeted at Alfred 2. Use -:class:`~workflow.Workflow3` if you want to use Alfred 3's new -features, such as :ref:`workflow variables ` or -more powerful modifiers. - -See :ref:`setup` in the :ref:`user-manual` for an example of how to set -up your Python script to best utilise the :class:`Workflow` object. - -""" - -from __future__ import print_function, unicode_literals - -import binascii -import cPickle -from copy import deepcopy -import json -import logging -import logging.handlers -import os -import pickle -import plistlib -import re -import shutil -import string -import subprocess -import sys -import time -import unicodedata - -try: - import xml.etree.cElementTree as ET -except ImportError: # pragma: no cover - import xml.etree.ElementTree as ET - -# imported to maintain API -from util import AcquisitionError # noqa: F401 -from util import ( - atomic_writer, - LockFile, - uninterruptible, -) - -#: Sentinel for properties that haven't been set yet (that might -#: correctly have the value ``None``) -UNSET = object() - -#################################################################### -# Standard system icons -#################################################################### - -# These icons are default macOS icons. They are super-high quality, and -# will be familiar to users. -# This library uses `ICON_ERROR` when a workflow dies in flames, so -# in my own workflows, I use `ICON_WARNING` for less fatal errors -# (e.g. bad user input, no results etc.) - -# The system icons are all in this directory. There are many more than -# are listed here - -ICON_ROOT = '/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources' - -ICON_ACCOUNT = os.path.join(ICON_ROOT, 'Accounts.icns') -ICON_BURN = os.path.join(ICON_ROOT, 'BurningIcon.icns') -ICON_CLOCK = os.path.join(ICON_ROOT, 'Clock.icns') -ICON_COLOR = os.path.join(ICON_ROOT, 'ProfileBackgroundColor.icns') -ICON_COLOUR = ICON_COLOR # Queen's English, if you please -ICON_EJECT = os.path.join(ICON_ROOT, 'EjectMediaIcon.icns') -# Shown when a workflow throws an error -ICON_ERROR = os.path.join(ICON_ROOT, 'AlertStopIcon.icns') -ICON_FAVORITE = os.path.join(ICON_ROOT, 'ToolbarFavoritesIcon.icns') -ICON_FAVOURITE = ICON_FAVORITE -ICON_GROUP = os.path.join(ICON_ROOT, 'GroupIcon.icns') -ICON_HELP = os.path.join(ICON_ROOT, 'HelpIcon.icns') -ICON_HOME = os.path.join(ICON_ROOT, 'HomeFolderIcon.icns') -ICON_INFO = os.path.join(ICON_ROOT, 'ToolbarInfo.icns') -ICON_NETWORK = os.path.join(ICON_ROOT, 'GenericNetworkIcon.icns') -ICON_NOTE = os.path.join(ICON_ROOT, 'AlertNoteIcon.icns') -ICON_SETTINGS = os.path.join(ICON_ROOT, 'ToolbarAdvanced.icns') -ICON_SWIRL = os.path.join(ICON_ROOT, 'ErasingIcon.icns') -ICON_SWITCH = os.path.join(ICON_ROOT, 'General.icns') -ICON_SYNC = os.path.join(ICON_ROOT, 'Sync.icns') -ICON_TRASH = os.path.join(ICON_ROOT, 'TrashIcon.icns') -ICON_USER = os.path.join(ICON_ROOT, 'UserIcon.icns') -ICON_WARNING = os.path.join(ICON_ROOT, 'AlertCautionIcon.icns') -ICON_WEB = os.path.join(ICON_ROOT, 'BookmarkIcon.icns') - -#################################################################### -# non-ASCII to ASCII diacritic folding. -# Used by `fold_to_ascii` method -#################################################################### - -ASCII_REPLACEMENTS = { - 'À': 'A', - 'Á': 'A', - 'Â': 'A', - 'Ã': 'A', - 'Ä': 'A', - 'Å': 'A', - 'Æ': 'AE', - 'Ç': 'C', - 'È': 'E', - 'É': 'E', - 'Ê': 'E', - 'Ë': 'E', - 'Ì': 'I', - 'Í': 'I', - 'Î': 'I', - 'Ï': 'I', - 'Ð': 'D', - 'Ñ': 'N', - 'Ò': 'O', - 'Ó': 'O', - 'Ô': 'O', - 'Õ': 'O', - 'Ö': 'O', - 'Ø': 'O', - 'Ù': 'U', - 'Ú': 'U', - 'Û': 'U', - 'Ü': 'U', - 'Ý': 'Y', - 'Þ': 'Th', - 'ß': 'ss', - 'à': 'a', - 'á': 'a', - 'â': 'a', - 'ã': 'a', - 'ä': 'a', - 'å': 'a', - 'æ': 'ae', - 'ç': 'c', - 'è': 'e', - 'é': 'e', - 'ê': 'e', - 'ë': 'e', - 'ì': 'i', - 'í': 'i', - 'î': 'i', - 'ï': 'i', - 'ð': 'd', - 'ñ': 'n', - 'ò': 'o', - 'ó': 'o', - 'ô': 'o', - 'õ': 'o', - 'ö': 'o', - 'ø': 'o', - 'ù': 'u', - 'ú': 'u', - 'û': 'u', - 'ü': 'u', - 'ý': 'y', - 'þ': 'th', - 'ÿ': 'y', - 'Ł': 'L', - 'ł': 'l', - 'Ń': 'N', - 'ń': 'n', - 'Ņ': 'N', - 'ņ': 'n', - 'Ň': 'N', - 'ň': 'n', - 'Ŋ': 'ng', - 'ŋ': 'NG', - 'Ō': 'O', - 'ō': 'o', - 'Ŏ': 'O', - 'ŏ': 'o', - 'Ő': 'O', - 'ő': 'o', - 'Œ': 'OE', - 'œ': 'oe', - 'Ŕ': 'R', - 'ŕ': 'r', - 'Ŗ': 'R', - 'ŗ': 'r', - 'Ř': 'R', - 'ř': 'r', - 'Ś': 'S', - 'ś': 's', - 'Ŝ': 'S', - 'ŝ': 's', - 'Ş': 'S', - 'ş': 's', - 'Š': 'S', - 'š': 's', - 'Ţ': 'T', - 'ţ': 't', - 'Ť': 'T', - 'ť': 't', - 'Ŧ': 'T', - 'ŧ': 't', - 'Ũ': 'U', - 'ũ': 'u', - 'Ū': 'U', - 'ū': 'u', - 'Ŭ': 'U', - 'ŭ': 'u', - 'Ů': 'U', - 'ů': 'u', - 'Ű': 'U', - 'ű': 'u', - 'Ŵ': 'W', - 'ŵ': 'w', - 'Ŷ': 'Y', - 'ŷ': 'y', - 'Ÿ': 'Y', - 'Ź': 'Z', - 'ź': 'z', - 'Ż': 'Z', - 'ż': 'z', - 'Ž': 'Z', - 'ž': 'z', - 'ſ': 's', - 'Α': 'A', - 'Β': 'B', - 'Γ': 'G', - 'Δ': 'D', - 'Ε': 'E', - 'Ζ': 'Z', - 'Η': 'E', - 'Θ': 'Th', - 'Ι': 'I', - 'Κ': 'K', - 'Λ': 'L', - 'Μ': 'M', - 'Ν': 'N', - 'Ξ': 'Ks', - 'Ο': 'O', - 'Π': 'P', - 'Ρ': 'R', - 'Σ': 'S', - 'Τ': 'T', - 'Υ': 'U', - 'Φ': 'Ph', - 'Χ': 'Kh', - 'Ψ': 'Ps', - 'Ω': 'O', - 'α': 'a', - 'β': 'b', - 'γ': 'g', - 'δ': 'd', - 'ε': 'e', - 'ζ': 'z', - 'η': 'e', - 'θ': 'th', - 'ι': 'i', - 'κ': 'k', - 'λ': 'l', - 'μ': 'm', - 'ν': 'n', - 'ξ': 'x', - 'ο': 'o', - 'π': 'p', - 'ρ': 'r', - 'ς': 's', - 'σ': 's', - 'τ': 't', - 'υ': 'u', - 'φ': 'ph', - 'χ': 'kh', - 'ψ': 'ps', - 'ω': 'o', - 'А': 'A', - 'Б': 'B', - 'В': 'V', - 'Г': 'G', - 'Д': 'D', - 'Е': 'E', - 'Ж': 'Zh', - 'З': 'Z', - 'И': 'I', - 'Й': 'I', - 'К': 'K', - 'Л': 'L', - 'М': 'M', - 'Н': 'N', - 'О': 'O', - 'П': 'P', - 'Р': 'R', - 'С': 'S', - 'Т': 'T', - 'У': 'U', - 'Ф': 'F', - 'Х': 'Kh', - 'Ц': 'Ts', - 'Ч': 'Ch', - 'Ш': 'Sh', - 'Щ': 'Shch', - 'Ъ': "'", - 'Ы': 'Y', - 'Ь': "'", - 'Э': 'E', - 'Ю': 'Iu', - 'Я': 'Ia', - 'а': 'a', - 'б': 'b', - 'в': 'v', - 'г': 'g', - 'д': 'd', - 'е': 'e', - 'ж': 'zh', - 'з': 'z', - 'и': 'i', - 'й': 'i', - 'к': 'k', - 'л': 'l', - 'м': 'm', - 'н': 'n', - 'о': 'o', - 'п': 'p', - 'р': 'r', - 'с': 's', - 'т': 't', - 'у': 'u', - 'ф': 'f', - 'х': 'kh', - 'ц': 'ts', - 'ч': 'ch', - 'ш': 'sh', - 'щ': 'shch', - 'ъ': "'", - 'ы': 'y', - 'ь': "'", - 'э': 'e', - 'ю': 'iu', - 'я': 'ia', - # 'ᴀ': '', - # 'ᴁ': '', - # 'ᴂ': '', - # 'ᴃ': '', - # 'ᴄ': '', - # 'ᴅ': '', - # 'ᴆ': '', - # 'ᴇ': '', - # 'ᴈ': '', - # 'ᴉ': '', - # 'ᴊ': '', - # 'ᴋ': '', - # 'ᴌ': '', - # 'ᴍ': '', - # 'ᴎ': '', - # 'ᴏ': '', - # 'ᴐ': '', - # 'ᴑ': '', - # 'ᴒ': '', - # 'ᴓ': '', - # 'ᴔ': '', - # 'ᴕ': '', - # 'ᴖ': '', - # 'ᴗ': '', - # 'ᴘ': '', - # 'ᴙ': '', - # 'ᴚ': '', - # 'ᴛ': '', - # 'ᴜ': '', - # 'ᴝ': '', - # 'ᴞ': '', - # 'ᴟ': '', - # 'ᴠ': '', - # 'ᴡ': '', - # 'ᴢ': '', - # 'ᴣ': '', - # 'ᴤ': '', - # 'ᴥ': '', - 'ᴦ': 'G', - 'ᴧ': 'L', - 'ᴨ': 'P', - 'ᴩ': 'R', - 'ᴪ': 'PS', - 'ẞ': 'Ss', - 'Ỳ': 'Y', - 'ỳ': 'y', - 'Ỵ': 'Y', - 'ỵ': 'y', - 'Ỹ': 'Y', - 'ỹ': 'y', -} - -#################################################################### -# Smart-to-dumb punctuation mapping -#################################################################### - -DUMB_PUNCTUATION = { - '‘': "'", - '’': "'", - '‚': "'", - '“': '"', - '”': '"', - '„': '"', - '–': '-', - '—': '-' -} - - -#################################################################### -# Used by `Workflow.filter` -#################################################################### - -# Anchor characters in a name -#: Characters that indicate the beginning of a "word" in CamelCase -INITIALS = string.ascii_uppercase + string.digits - -#: Split on non-letters, numbers -split_on_delimiters = re.compile('[^a-zA-Z0-9]').split - -# Match filter flags -#: Match items that start with ``query`` -MATCH_STARTSWITH = 1 -#: Match items whose capital letters start with ``query`` -MATCH_CAPITALS = 2 -#: Match items with a component "word" that matches ``query`` -MATCH_ATOM = 4 -#: Match items whose initials (based on atoms) start with ``query`` -MATCH_INITIALS_STARTSWITH = 8 -#: Match items whose initials (based on atoms) contain ``query`` -MATCH_INITIALS_CONTAIN = 16 -#: Combination of :const:`MATCH_INITIALS_STARTSWITH` and -#: :const:`MATCH_INITIALS_CONTAIN` -MATCH_INITIALS = 24 -#: Match items if ``query`` is a substring -MATCH_SUBSTRING = 32 -#: Match items if all characters in ``query`` appear in the item in order -MATCH_ALLCHARS = 64 -#: Combination of all other ``MATCH_*`` constants -MATCH_ALL = 127 - - -#################################################################### -# Used by `Workflow.check_update` -#################################################################### - -# Number of days to wait between checking for updates to the workflow -DEFAULT_UPDATE_FREQUENCY = 1 - - -#################################################################### -# Keychain access errors -#################################################################### - - -class KeychainError(Exception): - """Raised for unknown Keychain errors. - - Raised by methods :meth:`Workflow.save_password`, - :meth:`Workflow.get_password` and :meth:`Workflow.delete_password` - when ``security`` CLI app returns an unknown error code. - - """ - - -class PasswordNotFound(KeychainError): - """Password not in Keychain. - - Raised by method :meth:`Workflow.get_password` when ``account`` - is unknown to the Keychain. - - """ - - -class PasswordExists(KeychainError): - """Raised when trying to overwrite an existing account password. - - You should never receive this error: it is used internally - by the :meth:`Workflow.save_password` method to know if it needs - to delete the old password first (a Keychain implementation detail). - - """ - - -#################################################################### -# Helper functions -#################################################################### - -def isascii(text): - """Test if ``text`` contains only ASCII characters. - - :param text: text to test for ASCII-ness - :type text: ``unicode`` - :returns: ``True`` if ``text`` contains only ASCII characters - :rtype: ``Boolean`` - - """ - try: - text.encode('ascii') - except UnicodeEncodeError: - return False - return True - - -#################################################################### -# Implementation classes -#################################################################### - -class SerializerManager(object): - """Contains registered serializers. - - .. versionadded:: 1.8 - - A configured instance of this class is available at - :attr:`workflow.manager`. - - Use :meth:`register()` to register new (or replace - existing) serializers, which you can specify by name when calling - :class:`~workflow.Workflow` data storage methods. - - See :ref:`guide-serialization` and :ref:`guide-persistent-data` - for further information. - - """ - - def __init__(self): - """Create new SerializerManager object.""" - self._serializers = {} - - def register(self, name, serializer): - """Register ``serializer`` object under ``name``. - - Raises :class:`AttributeError` if ``serializer`` in invalid. - - .. note:: - - ``name`` will be used as the file extension of the saved files. - - :param name: Name to register ``serializer`` under - :type name: ``unicode`` or ``str`` - :param serializer: object with ``load()`` and ``dump()`` - methods - - """ - # Basic validation - getattr(serializer, 'load') - getattr(serializer, 'dump') - - self._serializers[name] = serializer - - def serializer(self, name): - """Return serializer object for ``name``. - - :param name: Name of serializer to return - :type name: ``unicode`` or ``str`` - :returns: serializer object or ``None`` if no such serializer - is registered. - - """ - return self._serializers.get(name) - - def unregister(self, name): - """Remove registered serializer with ``name``. - - Raises a :class:`ValueError` if there is no such registered - serializer. - - :param name: Name of serializer to remove - :type name: ``unicode`` or ``str`` - :returns: serializer object - - """ - if name not in self._serializers: - raise ValueError('No such serializer registered : {0}'.format( - name)) - - serializer = self._serializers[name] - del self._serializers[name] - - return serializer - - @property - def serializers(self): - """Return names of registered serializers.""" - return sorted(self._serializers.keys()) - - -class JSONSerializer(object): - """Wrapper around :mod:`json`. Sets ``indent`` and ``encoding``. - - .. versionadded:: 1.8 - - Use this serializer if you need readable data files. JSON doesn't - support Python objects as well as ``cPickle``/``pickle``, so be - careful which data you try to serialize as JSON. - - """ - - @classmethod - def load(cls, file_obj): - """Load serialized object from open JSON file. - - .. versionadded:: 1.8 - - :param file_obj: file handle - :type file_obj: ``file`` object - :returns: object loaded from JSON file - :rtype: object - - """ - return json.load(file_obj) - - @classmethod - def dump(cls, obj, file_obj): - """Serialize object ``obj`` to open JSON file. - - .. versionadded:: 1.8 - - :param obj: Python object to serialize - :type obj: JSON-serializable data structure - :param file_obj: file handle - :type file_obj: ``file`` object - - """ - return json.dump(obj, file_obj, indent=2, encoding='utf-8') - - -class CPickleSerializer(object): - """Wrapper around :mod:`cPickle`. Sets ``protocol``. - - .. versionadded:: 1.8 - - This is the default serializer and the best combination of speed and - flexibility. - - """ - - @classmethod - def load(cls, file_obj): - """Load serialized object from open pickle file. - - .. versionadded:: 1.8 - - :param file_obj: file handle - :type file_obj: ``file`` object - :returns: object loaded from pickle file - :rtype: object - - """ - return cPickle.load(file_obj) - - @classmethod - def dump(cls, obj, file_obj): - """Serialize object ``obj`` to open pickle file. - - .. versionadded:: 1.8 - - :param obj: Python object to serialize - :type obj: Python object - :param file_obj: file handle - :type file_obj: ``file`` object - - """ - return cPickle.dump(obj, file_obj, protocol=-1) - - -class PickleSerializer(object): - """Wrapper around :mod:`pickle`. Sets ``protocol``. - - .. versionadded:: 1.8 - - Use this serializer if you need to add custom pickling. - - """ - - @classmethod - def load(cls, file_obj): - """Load serialized object from open pickle file. - - .. versionadded:: 1.8 - - :param file_obj: file handle - :type file_obj: ``file`` object - :returns: object loaded from pickle file - :rtype: object - - """ - return pickle.load(file_obj) - - @classmethod - def dump(cls, obj, file_obj): - """Serialize object ``obj`` to open pickle file. - - .. versionadded:: 1.8 - - :param obj: Python object to serialize - :type obj: Python object - :param file_obj: file handle - :type file_obj: ``file`` object - - """ - return pickle.dump(obj, file_obj, protocol=-1) - - -# Set up default manager and register built-in serializers -manager = SerializerManager() -manager.register('cpickle', CPickleSerializer) -manager.register('pickle', PickleSerializer) -manager.register('json', JSONSerializer) - - -class Item(object): - """Represents a feedback item for Alfred. - - Generates Alfred-compliant XML for a single item. - - You probably shouldn't use this class directly, but via - :meth:`Workflow.add_item`. See :meth:`~Workflow.add_item` - for details of arguments. - - """ - - def __init__(self, title, subtitle='', modifier_subtitles=None, - arg=None, autocomplete=None, valid=False, uid=None, - icon=None, icontype=None, type=None, largetext=None, - copytext=None, quicklookurl=None): - """Same arguments as :meth:`Workflow.add_item`.""" - self.title = title - self.subtitle = subtitle - self.modifier_subtitles = modifier_subtitles or {} - self.arg = arg - self.autocomplete = autocomplete - self.valid = valid - self.uid = uid - self.icon = icon - self.icontype = icontype - self.type = type - self.largetext = largetext - self.copytext = copytext - self.quicklookurl = quicklookurl - - @property - def elem(self): - """Create and return feedback item for Alfred. - - :returns: :class:`ElementTree.Element ` - instance for this :class:`Item` instance. - - """ - # Attributes on element - attr = {} - if self.valid: - attr['valid'] = 'yes' - else: - attr['valid'] = 'no' - # Allow empty string for autocomplete. This is a useful value, - # as TABing the result will revert the query back to just the - # keyword - if self.autocomplete is not None: - attr['autocomplete'] = self.autocomplete - - # Optional attributes - for name in ('uid', 'type'): - value = getattr(self, name, None) - if value: - attr[name] = value - - root = ET.Element('item', attr) - ET.SubElement(root, 'title').text = self.title - ET.SubElement(root, 'subtitle').text = self.subtitle - - # Add modifier subtitles - for mod in ('cmd', 'ctrl', 'alt', 'shift', 'fn'): - if mod in self.modifier_subtitles: - ET.SubElement(root, 'subtitle', - {'mod': mod}).text = self.modifier_subtitles[mod] - - # Add arg as element instead of attribute on , as it's more - # flexible (newlines aren't allowed in attributes) - if self.arg: - ET.SubElement(root, 'arg').text = self.arg - - # Add icon if there is one - if self.icon: - if self.icontype: - attr = dict(type=self.icontype) - else: - attr = {} - ET.SubElement(root, 'icon', attr).text = self.icon - - if self.largetext: - ET.SubElement(root, 'text', - {'type': 'largetype'}).text = self.largetext - - if self.copytext: - ET.SubElement(root, 'text', - {'type': 'copy'}).text = self.copytext - - if self.quicklookurl: - ET.SubElement(root, 'quicklookurl').text = self.quicklookurl - - return root - - -class Settings(dict): - """A dictionary that saves itself when changed. - - Dictionary keys & values will be saved as a JSON file - at ``filepath``. If the file does not exist, the dictionary - (and settings file) will be initialised with ``defaults``. - - :param filepath: where to save the settings - :type filepath: :class:`unicode` - :param defaults: dict of default settings - :type defaults: :class:`dict` - - - An appropriate instance is provided by :class:`Workflow` instances at - :attr:`Workflow.settings`. - - """ - - def __init__(self, filepath, defaults=None): - """Create new :class:`Settings` object.""" - super(Settings, self).__init__() - self._filepath = filepath - self._nosave = False - self._original = {} - if os.path.exists(self._filepath): - self._load() - elif defaults: - for key, val in defaults.items(): - self[key] = val - self.save() # save default settings - - def _load(self): - """Load cached settings from JSON file `self._filepath`.""" - data = {} - with LockFile(self._filepath, 0.5): - with open(self._filepath, 'rb') as fp: - data.update(json.load(fp)) - - self._original = deepcopy(data) - - self._nosave = True - self.update(data) - self._nosave = False - - @uninterruptible - def save(self): - """Save settings to JSON file specified in ``self._filepath``. - - If you're using this class via :attr:`Workflow.settings`, which - you probably are, ``self._filepath`` will be ``settings.json`` - in your workflow's data directory (see :attr:`~Workflow.datadir`). - """ - if self._nosave: - return - - data = {} - data.update(self) - - with LockFile(self._filepath, 0.5): - with atomic_writer(self._filepath, 'wb') as fp: - json.dump(data, fp, sort_keys=True, indent=2, - encoding='utf-8') - - # dict methods - def __setitem__(self, key, value): - """Implement :class:`dict` interface.""" - if self._original.get(key) != value: - super(Settings, self).__setitem__(key, value) - self.save() - - def __delitem__(self, key): - """Implement :class:`dict` interface.""" - super(Settings, self).__delitem__(key) - self.save() - - def update(self, *args, **kwargs): - """Override :class:`dict` method to save on update.""" - super(Settings, self).update(*args, **kwargs) - self.save() - - def setdefault(self, key, value=None): - """Override :class:`dict` method to save on update.""" - ret = super(Settings, self).setdefault(key, value) - self.save() - return ret - - -class Workflow(object): - """The ``Workflow`` object is the main interface to Alfred-Workflow. - - It provides APIs for accessing the Alfred/workflow environment, - storing & caching data, using Keychain, and generating Script - Filter feedback. - - ``Workflow`` is compatible with Alfred 2+. Subclass - :class:`~workflow.Workflow3` provides additional features, - only available in Alfred 3+, such as workflow variables. - - :param default_settings: default workflow settings. If no settings file - exists, :class:`Workflow.settings` will be pre-populated with - ``default_settings``. - :type default_settings: :class:`dict` - :param update_settings: settings for updating your workflow from - GitHub releases. The only required key is ``github_slug``, - whose value must take the form of ``username/repo``. - If specified, ``Workflow`` will check the repo's releases - for updates. Your workflow must also have a semantic version - number. Please see the :ref:`User Manual ` and - `update API docs ` for more information. - :type update_settings: :class:`dict` - :param input_encoding: encoding of command line arguments. You - should probably leave this as the default (``utf-8``), which - is the encoding Alfred uses. - :type input_encoding: :class:`unicode` - :param normalization: normalisation to apply to CLI args. - See :meth:`Workflow.decode` for more details. - :type normalization: :class:`unicode` - :param capture_args: Capture and act on ``workflow:*`` arguments. See - :ref:`Magic arguments ` for details. - :type capture_args: :class:`Boolean` - :param libraries: sequence of paths to directories containing - libraries. These paths will be prepended to ``sys.path``. - :type libraries: :class:`tuple` or :class:`list` - :param help_url: URL to webpage where a user can ask for help with - the workflow, report bugs, etc. This could be the GitHub repo - or a page on AlfredForum.com. If your workflow throws an error, - this URL will be displayed in the log and Alfred's debugger. It can - also be opened directly in a web browser with the ``workflow:help`` - :ref:`magic argument `. - :type help_url: :class:`unicode` or :class:`str` - - """ - - # Which class to use to generate feedback items. You probably - # won't want to change this - item_class = Item - - def __init__(self, default_settings=None, update_settings=None, - input_encoding='utf-8', normalization='NFC', - capture_args=True, libraries=None, - help_url=None): - """Create new :class:`Workflow` object.""" - self._default_settings = default_settings or {} - self._update_settings = update_settings or {} - self._input_encoding = input_encoding - self._normalizsation = normalization - self._capture_args = capture_args - self.help_url = help_url - self._workflowdir = None - self._settings_path = None - self._settings = None - self._bundleid = None - self._debugging = None - self._name = None - self._cache_serializer = 'cpickle' - self._data_serializer = 'cpickle' - self._info = None - self._info_loaded = False - self._logger = None - self._items = [] - self._alfred_env = None - # Version number of the workflow - self._version = UNSET - # Version from last workflow run - self._last_version_run = UNSET - # Cache for regex patterns created for filter keys - self._search_pattern_cache = {} - #: Prefix for all magic arguments. - #: The default value is ``workflow:`` so keyword - #: ``config`` would match user query ``workflow:config``. - self.magic_prefix = 'workflow:' - #: Mapping of available magic arguments. The built-in magic - #: arguments are registered by default. To add your own magic arguments - #: (or override built-ins), add a key:value pair where the key is - #: what the user should enter (prefixed with :attr:`magic_prefix`) - #: and the value is a callable that will be called when the argument - #: is entered. If you would like to display a message in Alfred, the - #: function should return a ``unicode`` string. - #: - #: By default, the magic arguments documented - #: :ref:`here ` are registered. - self.magic_arguments = {} - - self._register_default_magic() - - if libraries: - sys.path = libraries + sys.path - - #################################################################### - # API methods - #################################################################### - - # info.plist contents and alfred_* environment variables ---------- - - @property - def alfred_version(self): - """Alfred version as :class:`~workflow.update.Version` object.""" - from update import Version - return Version(self.alfred_env.get('version')) - - @property - def alfred_env(self): - """Dict of Alfred's environmental variables minus ``alfred_`` prefix. - - .. versionadded:: 1.7 - - The variables Alfred 2.4+ exports are: - - ============================ ========================================= - Variable Description - ============================ ========================================= - debug Set to ``1`` if Alfred's debugger is - open, otherwise unset. - preferences Path to Alfred.alfredpreferences - (where your workflows and settings are - stored). - preferences_localhash Machine-specific preferences are stored - in ``Alfred.alfredpreferences/preferences/local/`` - (see ``preferences`` above for - the path to ``Alfred.alfredpreferences``) - theme ID of selected theme - theme_background Background colour of selected theme in - format ``rgba(r,g,b,a)`` - theme_subtext Show result subtext. - ``0`` = Always, - ``1`` = Alternative actions only, - ``2`` = Selected result only, - ``3`` = Never - version Alfred version number, e.g. ``'2.4'`` - version_build Alfred build number, e.g. ``277`` - workflow_bundleid Bundle ID, e.g. - ``net.deanishe.alfred-mailto`` - workflow_cache Path to workflow's cache directory - workflow_data Path to workflow's data directory - workflow_name Name of current workflow - workflow_uid UID of workflow - workflow_version The version number specified in the - workflow configuration sheet/info.plist - ============================ ========================================= - - **Note:** all values are Unicode strings except ``version_build`` and - ``theme_subtext``, which are integers. - - :returns: ``dict`` of Alfred's environmental variables without the - ``alfred_`` prefix, e.g. ``preferences``, ``workflow_data``. - - """ - if self._alfred_env is not None: - return self._alfred_env - - data = {} - - for key in ( - 'debug', - 'preferences', - 'preferences_localhash', - 'theme', - 'theme_background', - 'theme_subtext', - 'version', - 'version_build', - 'workflow_bundleid', - 'workflow_cache', - 'workflow_data', - 'workflow_name', - 'workflow_uid', - 'workflow_version'): - - value = os.getenv('alfred_' + key, '') - - if value: - if key in ('debug', 'version_build', 'theme_subtext'): - value = int(value) - else: - value = self.decode(value) - - data[key] = value - - self._alfred_env = data - - return self._alfred_env - - @property - def info(self): - """:class:`dict` of ``info.plist`` contents.""" - if not self._info_loaded: - self._load_info_plist() - return self._info - - @property - def bundleid(self): - """Workflow bundle ID from environmental vars or ``info.plist``. - - :returns: bundle ID - :rtype: ``unicode`` - - """ - if not self._bundleid: - if self.alfred_env.get('workflow_bundleid'): - self._bundleid = self.alfred_env.get('workflow_bundleid') - else: - self._bundleid = unicode(self.info['bundleid'], 'utf-8') - - return self._bundleid - - @property - def debugging(self): - """Whether Alfred's debugger is open. - - :returns: ``True`` if Alfred's debugger is open. - :rtype: ``bool`` - - """ - return self.alfred_env.get('debug') == 1 - - @property - def name(self): - """Workflow name from Alfred's environmental vars or ``info.plist``. - - :returns: workflow name - :rtype: ``unicode`` - - """ - if not self._name: - if self.alfred_env.get('workflow_name'): - self._name = self.decode(self.alfred_env.get('workflow_name')) - else: - self._name = self.decode(self.info['name']) - - return self._name - - @property - def version(self): - """Return the version of the workflow. - - .. versionadded:: 1.9.10 - - Get the workflow version from environment variable, - the ``update_settings`` dict passed on - instantiation, the ``version`` file located in the workflow's - root directory or ``info.plist``. Return ``None`` if none - exists or :class:`ValueError` if the version number is invalid - (i.e. not semantic). - - :returns: Version of the workflow (not Alfred-Workflow) - :rtype: :class:`~workflow.update.Version` object - - """ - if self._version is UNSET: - - version = None - # environment variable has priority - if self.alfred_env.get('workflow_version'): - version = self.alfred_env['workflow_version'] - - # Try `update_settings` - elif self._update_settings: - version = self._update_settings.get('version') - - # `version` file - if not version: - filepath = self.workflowfile('version') - - if os.path.exists(filepath): - with open(filepath, 'rb') as fileobj: - version = fileobj.read() - - # info.plist - if not version: - version = self.info.get('version') - - if version: - from update import Version - version = Version(version) - - self._version = version - - return self._version - - # Workflow utility methods ----------------------------------------- - - @property - def args(self): - """Return command line args as normalised unicode. - - Args are decoded and normalised via :meth:`~Workflow.decode`. - - The encoding and normalisation are the ``input_encoding`` and - ``normalization`` arguments passed to :class:`Workflow` (``UTF-8`` - and ``NFC`` are the defaults). - - If :class:`Workflow` is called with ``capture_args=True`` - (the default), :class:`Workflow` will look for certain - ``workflow:*`` args and, if found, perform the corresponding - actions and exit the workflow. - - See :ref:`Magic arguments ` for details. - - """ - msg = None - args = [self.decode(arg) for arg in sys.argv[1:]] - - # Handle magic args - if len(args) and self._capture_args: - for name in self.magic_arguments: - key = '{0}{1}'.format(self.magic_prefix, name) - if key in args: - msg = self.magic_arguments[name]() - - if msg: - self.logger.debug(msg) - if not sys.stdout.isatty(): # Show message in Alfred - self.add_item(msg, valid=False, icon=ICON_INFO) - self.send_feedback() - sys.exit(0) - return args - - @property - def cachedir(self): - """Path to workflow's cache directory. - - The cache directory is a subdirectory of Alfred's own cache directory - in ``~/Library/Caches``. The full path is in Alfred 4+ is: - - ``~/Library/Caches/com.runningwithcrayons.Alfred/Workflow Data/`` - - For earlier versions: - - ``~/Library/Caches/com.runningwithcrayons.Alfred-X/Workflow Data/`` - - where ``Alfred-X`` may be ``Alfred-2`` or ``Alfred-3``. - - Returns: - unicode: full path to workflow's cache directory - - """ - if self.alfred_env.get('workflow_cache'): - dirpath = self.alfred_env.get('workflow_cache') - - else: - dirpath = self._default_cachedir - - return self._create(dirpath) - - @property - def _default_cachedir(self): - """Alfred 2's default cache directory.""" - return os.path.join( - os.path.expanduser( - '~/Library/Caches/com.runningwithcrayons.Alfred-2/' - 'Workflow Data/'), - self.bundleid) - - @property - def datadir(self): - """Path to workflow's data directory. - - The data directory is a subdirectory of Alfred's own data directory in - ``~/Library/Application Support``. The full path for Alfred 4+ is: - - ``~/Library/Application Support/Alfred/Workflow Data/`` - - For earlier versions, the path is: - - ``~/Library/Application Support/Alfred X/Workflow Data/`` - - where ``Alfred X` is ``Alfred 2`` or ``Alfred 3``. - - Returns: - unicode: full path to workflow data directory - - """ - if self.alfred_env.get('workflow_data'): - dirpath = self.alfred_env.get('workflow_data') - - else: - dirpath = self._default_datadir - - return self._create(dirpath) - - @property - def _default_datadir(self): - """Alfred 2's default data directory.""" - return os.path.join(os.path.expanduser( - '~/Library/Application Support/Alfred 2/Workflow Data/'), - self.bundleid) - - @property - def workflowdir(self): - """Path to workflow's root directory (where ``info.plist`` is). - - Returns: - unicode: full path to workflow root directory - - """ - if not self._workflowdir: - # Try the working directory first, then the directory - # the library is in. CWD will be the workflow root if - # a workflow is being run in Alfred - candidates = [ - os.path.abspath(os.getcwdu()), - os.path.dirname(os.path.abspath(os.path.dirname(__file__)))] - - # climb the directory tree until we find `info.plist` - for dirpath in candidates: - - # Ensure directory path is Unicode - dirpath = self.decode(dirpath) - - while True: - if os.path.exists(os.path.join(dirpath, 'info.plist')): - self._workflowdir = dirpath - break - - elif dirpath == '/': - # no `info.plist` found - break - - # Check the parent directory - dirpath = os.path.dirname(dirpath) - - # No need to check other candidates - if self._workflowdir: - break - - if not self._workflowdir: - raise IOError("'info.plist' not found in directory tree") - - return self._workflowdir - - def cachefile(self, filename): - """Path to ``filename`` in workflow's cache directory. - - Return absolute path to ``filename`` within your workflow's - :attr:`cache directory `. - - :param filename: basename of file - :type filename: ``unicode`` - :returns: full path to file within cache directory - :rtype: ``unicode`` - - """ - return os.path.join(self.cachedir, filename) - - def datafile(self, filename): - """Path to ``filename`` in workflow's data directory. - - Return absolute path to ``filename`` within your workflow's - :attr:`data directory `. - - :param filename: basename of file - :type filename: ``unicode`` - :returns: full path to file within data directory - :rtype: ``unicode`` - - """ - return os.path.join(self.datadir, filename) - - def workflowfile(self, filename): - """Return full path to ``filename`` in workflow's root directory. - - :param filename: basename of file - :type filename: ``unicode`` - :returns: full path to file within data directory - :rtype: ``unicode`` - - """ - return os.path.join(self.workflowdir, filename) - - @property - def logfile(self): - """Path to logfile. - - :returns: path to logfile within workflow's cache directory - :rtype: ``unicode`` - - """ - return self.cachefile('%s.log' % self.bundleid) - - @property - def logger(self): - """Logger that logs to both console and a log file. - - If Alfred's debugger is open, log level will be ``DEBUG``, - else it will be ``INFO``. - - Use :meth:`open_log` to open the log file in Console. - - :returns: an initialised :class:`~logging.Logger` - - """ - if self._logger: - return self._logger - - # Initialise new logger and optionally handlers - logger = logging.getLogger('') - - # Only add one set of handlers - # Exclude from coverage, as pytest will have configured the - # root logger already - if not len(logger.handlers): # pragma: no cover - - fmt = logging.Formatter( - '%(asctime)s %(filename)s:%(lineno)s' - ' %(levelname)-8s %(message)s', - datefmt='%H:%M:%S') - - logfile = logging.handlers.RotatingFileHandler( - self.logfile, - maxBytes=1024 * 1024, - backupCount=1) - logfile.setFormatter(fmt) - logger.addHandler(logfile) - - console = logging.StreamHandler() - console.setFormatter(fmt) - logger.addHandler(console) - - if self.debugging: - logger.setLevel(logging.DEBUG) - else: - logger.setLevel(logging.INFO) - - self._logger = logger - - return self._logger - - @logger.setter - def logger(self, logger): - """Set a custom logger. - - :param logger: The logger to use - :type logger: `~logging.Logger` instance - - """ - self._logger = logger - - @property - def settings_path(self): - """Path to settings file within workflow's data directory. - - :returns: path to ``settings.json`` file - :rtype: ``unicode`` - - """ - if not self._settings_path: - self._settings_path = self.datafile('settings.json') - return self._settings_path - - @property - def settings(self): - """Return a dictionary subclass that saves itself when changed. - - See :ref:`guide-settings` in the :ref:`user-manual` for more - information on how to use :attr:`settings` and **important - limitations** on what it can do. - - :returns: :class:`~workflow.workflow.Settings` instance - initialised from the data in JSON file at - :attr:`settings_path` or if that doesn't exist, with the - ``default_settings`` :class:`dict` passed to - :class:`Workflow` on instantiation. - :rtype: :class:`~workflow.workflow.Settings` instance - - """ - if not self._settings: - self.logger.debug('reading settings from %s', self.settings_path) - self._settings = Settings(self.settings_path, - self._default_settings) - return self._settings - - @property - def cache_serializer(self): - """Name of default cache serializer. - - .. versionadded:: 1.8 - - This serializer is used by :meth:`cache_data()` and - :meth:`cached_data()` - - See :class:`SerializerManager` for details. - - :returns: serializer name - :rtype: ``unicode`` - - """ - return self._cache_serializer - - @cache_serializer.setter - def cache_serializer(self, serializer_name): - """Set the default cache serialization format. - - .. versionadded:: 1.8 - - This serializer is used by :meth:`cache_data()` and - :meth:`cached_data()` - - The specified serializer must already by registered with the - :class:`SerializerManager` at `~workflow.workflow.manager`, - otherwise a :class:`ValueError` will be raised. - - :param serializer_name: Name of default serializer to use. - :type serializer_name: - - """ - if manager.serializer(serializer_name) is None: - raise ValueError( - 'Unknown serializer : `{0}`. Register your serializer ' - 'with `manager` first.'.format(serializer_name)) - - self.logger.debug('default cache serializer: %s', serializer_name) - - self._cache_serializer = serializer_name - - @property - def data_serializer(self): - """Name of default data serializer. - - .. versionadded:: 1.8 - - This serializer is used by :meth:`store_data()` and - :meth:`stored_data()` - - See :class:`SerializerManager` for details. - - :returns: serializer name - :rtype: ``unicode`` - - """ - return self._data_serializer - - @data_serializer.setter - def data_serializer(self, serializer_name): - """Set the default cache serialization format. - - .. versionadded:: 1.8 - - This serializer is used by :meth:`store_data()` and - :meth:`stored_data()` - - The specified serializer must already by registered with the - :class:`SerializerManager` at `~workflow.workflow.manager`, - otherwise a :class:`ValueError` will be raised. - - :param serializer_name: Name of serializer to use by default. - - """ - if manager.serializer(serializer_name) is None: - raise ValueError( - 'Unknown serializer : `{0}`. Register your serializer ' - 'with `manager` first.'.format(serializer_name)) - - self.logger.debug('default data serializer: %s', serializer_name) - - self._data_serializer = serializer_name - - def stored_data(self, name): - """Retrieve data from data directory. - - Returns ``None`` if there are no data stored under ``name``. - - .. versionadded:: 1.8 - - :param name: name of datastore - - """ - metadata_path = self.datafile('.{0}.alfred-workflow'.format(name)) - - if not os.path.exists(metadata_path): - self.logger.debug('no data stored for `%s`', name) - return None - - with open(metadata_path, 'rb') as file_obj: - serializer_name = file_obj.read().strip() - - serializer = manager.serializer(serializer_name) - - if serializer is None: - raise ValueError( - 'Unknown serializer `{0}`. Register a corresponding ' - 'serializer with `manager.register()` ' - 'to load this data.'.format(serializer_name)) - - self.logger.debug('data `%s` stored as `%s`', name, serializer_name) - - filename = '{0}.{1}'.format(name, serializer_name) - data_path = self.datafile(filename) - - if not os.path.exists(data_path): - self.logger.debug('no data stored: %s', name) - if os.path.exists(metadata_path): - os.unlink(metadata_path) - - return None - - with open(data_path, 'rb') as file_obj: - data = serializer.load(file_obj) - - self.logger.debug('stored data loaded: %s', data_path) - - return data - - def store_data(self, name, data, serializer=None): - """Save data to data directory. - - .. versionadded:: 1.8 - - If ``data`` is ``None``, the datastore will be deleted. - - Note that the datastore does NOT support mutliple threads. - - :param name: name of datastore - :param data: object(s) to store. **Note:** some serializers - can only handled certain types of data. - :param serializer: name of serializer to use. If no serializer - is specified, the default will be used. See - :class:`SerializerManager` for more information. - :returns: data in datastore or ``None`` - - """ - # Ensure deletion is not interrupted by SIGTERM - @uninterruptible - def delete_paths(paths): - """Clear one or more data stores""" - for path in paths: - if os.path.exists(path): - os.unlink(path) - self.logger.debug('deleted data file: %s', path) - - serializer_name = serializer or self.data_serializer - - # In order for `stored_data()` to be able to load data stored with - # an arbitrary serializer, yet still have meaningful file extensions, - # the format (i.e. extension) is saved to an accompanying file - metadata_path = self.datafile('.{0}.alfred-workflow'.format(name)) - filename = '{0}.{1}'.format(name, serializer_name) - data_path = self.datafile(filename) - - if data_path == self.settings_path: - raise ValueError( - 'Cannot save data to' + - '`{0}` with format `{1}`. '.format(name, serializer_name) + - "This would overwrite Alfred-Workflow's settings file.") - - serializer = manager.serializer(serializer_name) - - if serializer is None: - raise ValueError( - 'Invalid serializer `{0}`. Register your serializer with ' - '`manager.register()` first.'.format(serializer_name)) - - if data is None: # Delete cached data - delete_paths((metadata_path, data_path)) - return - - # Ensure write is not interrupted by SIGTERM - @uninterruptible - def _store(): - # Save file extension - with atomic_writer(metadata_path, 'wb') as file_obj: - file_obj.write(serializer_name) - - with atomic_writer(data_path, 'wb') as file_obj: - serializer.dump(data, file_obj) - - _store() - - self.logger.debug('saved data: %s', data_path) - - def cached_data(self, name, data_func=None, max_age=60): - """Return cached data if younger than ``max_age`` seconds. - - Retrieve data from cache or re-generate and re-cache data if - stale/non-existant. If ``max_age`` is 0, return cached data no - matter how old. - - :param name: name of datastore - :param data_func: function to (re-)generate data. - :type data_func: ``callable`` - :param max_age: maximum age of cached data in seconds - :type max_age: ``int`` - :returns: cached data, return value of ``data_func`` or ``None`` - if ``data_func`` is not set - - """ - serializer = manager.serializer(self.cache_serializer) - - cache_path = self.cachefile('%s.%s' % (name, self.cache_serializer)) - age = self.cached_data_age(name) - - if (age < max_age or max_age == 0) and os.path.exists(cache_path): - - with open(cache_path, 'rb') as file_obj: - self.logger.debug('loading cached data: %s', cache_path) - return serializer.load(file_obj) - - if not data_func: - return None - - data = data_func() - self.cache_data(name, data) - - return data - - def cache_data(self, name, data): - """Save ``data`` to cache under ``name``. - - If ``data`` is ``None``, the corresponding cache file will be - deleted. - - :param name: name of datastore - :param data: data to store. This may be any object supported by - the cache serializer - - """ - serializer = manager.serializer(self.cache_serializer) - - cache_path = self.cachefile('%s.%s' % (name, self.cache_serializer)) - - if data is None: - if os.path.exists(cache_path): - os.unlink(cache_path) - self.logger.debug('deleted cache file: %s', cache_path) - return - - with atomic_writer(cache_path, 'wb') as file_obj: - serializer.dump(data, file_obj) - - self.logger.debug('cached data: %s', cache_path) - - def cached_data_fresh(self, name, max_age): - """Whether cache `name` is less than `max_age` seconds old. - - :param name: name of datastore - :param max_age: maximum age of data in seconds - :type max_age: ``int`` - :returns: ``True`` if data is less than ``max_age`` old, else - ``False`` - - """ - age = self.cached_data_age(name) - - if not age: - return False - - return age < max_age - - def cached_data_age(self, name): - """Return age in seconds of cache `name` or 0 if cache doesn't exist. - - :param name: name of datastore - :type name: ``unicode`` - :returns: age of datastore in seconds - :rtype: ``int`` - - """ - cache_path = self.cachefile('%s.%s' % (name, self.cache_serializer)) - - if not os.path.exists(cache_path): - return 0 - - return time.time() - os.stat(cache_path).st_mtime - - def filter(self, query, items, key=lambda x: x, ascending=False, - include_score=False, min_score=0, max_results=0, - match_on=MATCH_ALL, fold_diacritics=True): - """Fuzzy search filter. Returns list of ``items`` that match ``query``. - - ``query`` is case-insensitive. Any item that does not contain the - entirety of ``query`` is rejected. - - If ``query`` is an empty string or contains only whitespace, - all items will match. - - :param query: query to test items against - :type query: ``unicode`` - :param items: iterable of items to test - :type items: ``list`` or ``tuple`` - :param key: function to get comparison key from ``items``. - Must return a ``unicode`` string. The default simply returns - the item. - :type key: ``callable`` - :param ascending: set to ``True`` to get worst matches first - :type ascending: ``Boolean`` - :param include_score: Useful for debugging the scoring algorithm. - If ``True``, results will be a list of tuples - ``(item, score, rule)``. - :type include_score: ``Boolean`` - :param min_score: If non-zero, ignore results with a score lower - than this. - :type min_score: ``int`` - :param max_results: If non-zero, prune results list to this length. - :type max_results: ``int`` - :param match_on: Filter option flags. Bitwise-combined list of - ``MATCH_*`` constants (see below). - :type match_on: ``int`` - :param fold_diacritics: Convert search keys to ASCII-only - characters if ``query`` only contains ASCII characters. - :type fold_diacritics: ``Boolean`` - :returns: list of ``items`` matching ``query`` or list of - ``(item, score, rule)`` `tuples` if ``include_score`` is ``True``. - ``rule`` is the ``MATCH_*`` rule that matched the item. - :rtype: ``list`` - - **Matching rules** - - By default, :meth:`filter` uses all of the following flags (i.e. - :const:`MATCH_ALL`). The tests are always run in the given order: - - 1. :const:`MATCH_STARTSWITH` - Item search key starts with ``query`` (case-insensitive). - 2. :const:`MATCH_CAPITALS` - The list of capital letters in item search key starts with - ``query`` (``query`` may be lower-case). E.g., ``of`` - would match ``OmniFocus``, ``gc`` would match ``Google Chrome``. - 3. :const:`MATCH_ATOM` - Search key is split into "atoms" on non-word characters - (.,-,' etc.). Matches if ``query`` is one of these atoms - (case-insensitive). - 4. :const:`MATCH_INITIALS_STARTSWITH` - Initials are the first characters of the above-described - "atoms" (case-insensitive). - 5. :const:`MATCH_INITIALS_CONTAIN` - ``query`` is a substring of the above-described initials. - 6. :const:`MATCH_INITIALS` - Combination of (4) and (5). - 7. :const:`MATCH_SUBSTRING` - ``query`` is a substring of item search key (case-insensitive). - 8. :const:`MATCH_ALLCHARS` - All characters in ``query`` appear in item search key in - the same order (case-insensitive). - 9. :const:`MATCH_ALL` - Combination of all the above. - - - :const:`MATCH_ALLCHARS` is considerably slower than the other - tests and provides much less accurate results. - - **Examples:** - - To ignore :const:`MATCH_ALLCHARS` (tends to provide the worst - matches and is expensive to run), use - ``match_on=MATCH_ALL ^ MATCH_ALLCHARS``. - - To match only on capitals, use ``match_on=MATCH_CAPITALS``. - - To match only on startswith and substring, use - ``match_on=MATCH_STARTSWITH | MATCH_SUBSTRING``. - - **Diacritic folding** - - .. versionadded:: 1.3 - - If ``fold_diacritics`` is ``True`` (the default), and ``query`` - contains only ASCII characters, non-ASCII characters in search keys - will be converted to ASCII equivalents (e.g. **ü** -> **u**, - **ß** -> **ss**, **é** -> **e**). - - See :const:`ASCII_REPLACEMENTS` for all replacements. - - If ``query`` contains non-ASCII characters, search keys will not be - altered. - - """ - if not query: - return items - - # Remove preceding/trailing spaces - query = query.strip() - - if not query: - return items - - # Use user override if there is one - fold_diacritics = self.settings.get('__workflow_diacritic_folding', - fold_diacritics) - - results = [] - - for item in items: - skip = False - score = 0 - words = [s.strip() for s in query.split(' ')] - value = key(item).strip() - if value == '': - continue - for word in words: - if word == '': - continue - s, rule = self._filter_item(value, word, match_on, - fold_diacritics) - - if not s: # Skip items that don't match part of the query - skip = True - score += s - - if skip: - continue - - if score: - # use "reversed" `score` (i.e. highest becomes lowest) and - # `value` as sort key. This means items with the same score - # will be sorted in alphabetical not reverse alphabetical order - results.append(((100.0 / score, value.lower(), score), - (item, score, rule))) - - # sort on keys, then discard the keys - results.sort(reverse=ascending) - results = [t[1] for t in results] - - if min_score: - results = [r for r in results if r[1] > min_score] - - if max_results and len(results) > max_results: - results = results[:max_results] - - # return list of ``(item, score, rule)`` - if include_score: - return results - # just return list of items - return [t[0] for t in results] - - def _filter_item(self, value, query, match_on, fold_diacritics): - """Filter ``value`` against ``query`` using rules ``match_on``. - - :returns: ``(score, rule)`` - - """ - query = query.lower() - - if not isascii(query): - fold_diacritics = False - - if fold_diacritics: - value = self.fold_to_ascii(value) - - # pre-filter any items that do not contain all characters - # of ``query`` to save on running several more expensive tests - if not set(query) <= set(value.lower()): - - return (0, None) - - # item starts with query - if match_on & MATCH_STARTSWITH and value.lower().startswith(query): - score = 100.0 - (len(value) / len(query)) - - return (score, MATCH_STARTSWITH) - - # query matches capitalised letters in item, - # e.g. of = OmniFocus - if match_on & MATCH_CAPITALS: - initials = ''.join([c for c in value if c in INITIALS]) - if initials.lower().startswith(query): - score = 100.0 - (len(initials) / len(query)) - - return (score, MATCH_CAPITALS) - - # split the item into "atoms", i.e. words separated by - # spaces or other non-word characters - if (match_on & MATCH_ATOM or - match_on & MATCH_INITIALS_CONTAIN or - match_on & MATCH_INITIALS_STARTSWITH): - atoms = [s.lower() for s in split_on_delimiters(value)] - # print('atoms : %s --> %s' % (value, atoms)) - # initials of the atoms - initials = ''.join([s[0] for s in atoms if s]) - - if match_on & MATCH_ATOM: - # is `query` one of the atoms in item? - # similar to substring, but scores more highly, as it's - # a word within the item - if query in atoms: - score = 100.0 - (len(value) / len(query)) - - return (score, MATCH_ATOM) - - # `query` matches start (or all) of the initials of the - # atoms, e.g. ``himym`` matches "How I Met Your Mother" - # *and* "how i met your mother" (the ``capitals`` rule only - # matches the former) - if (match_on & MATCH_INITIALS_STARTSWITH and - initials.startswith(query)): - score = 100.0 - (len(initials) / len(query)) - - return (score, MATCH_INITIALS_STARTSWITH) - - # `query` is a substring of initials, e.g. ``doh`` matches - # "The Dukes of Hazzard" - elif (match_on & MATCH_INITIALS_CONTAIN and - query in initials): - score = 95.0 - (len(initials) / len(query)) - - return (score, MATCH_INITIALS_CONTAIN) - - # `query` is a substring of item - if match_on & MATCH_SUBSTRING and query in value.lower(): - score = 90.0 - (len(value) / len(query)) - - return (score, MATCH_SUBSTRING) - - # finally, assign a score based on how close together the - # characters in `query` are in item. - if match_on & MATCH_ALLCHARS: - search = self._search_for_query(query) - match = search(value) - if match: - score = 100.0 / ((1 + match.start()) * - (match.end() - match.start() + 1)) - - return (score, MATCH_ALLCHARS) - - # Nothing matched - return (0, None) - - def _search_for_query(self, query): - if query in self._search_pattern_cache: - return self._search_pattern_cache[query] - - # Build pattern: include all characters - pattern = [] - for c in query: - # pattern.append('[^{0}]*{0}'.format(re.escape(c))) - pattern.append('.*?{0}'.format(re.escape(c))) - pattern = ''.join(pattern) - search = re.compile(pattern, re.IGNORECASE).search - - self._search_pattern_cache[query] = search - return search - - def run(self, func, text_errors=False): - """Call ``func`` to run your workflow. - - :param func: Callable to call with ``self`` (i.e. the :class:`Workflow` - instance) as first argument. - :param text_errors: Emit error messages in plain text, not in - Alfred's XML/JSON feedback format. Use this when you're not - running Alfred-Workflow in a Script Filter and would like - to pass the error message to, say, a notification. - :type text_errors: ``Boolean`` - - ``func`` will be called with :class:`Workflow` instance as first - argument. - - ``func`` should be the main entry point to your workflow. - - Any exceptions raised will be logged and an error message will be - output to Alfred. - - """ - start = time.time() - - # Write to debugger to ensure "real" output starts on a new line - print('.', file=sys.stderr) - - # Call workflow's entry function/method within a try-except block - # to catch any errors and display an error message in Alfred - try: - if self.version: - self.logger.debug('---------- %s (%s) ----------', - self.name, self.version) - else: - self.logger.debug('---------- %s ----------', self.name) - - # Run update check if configured for self-updates. - # This call has to go in the `run` try-except block, as it will - # initialise `self.settings`, which will raise an exception - # if `settings.json` isn't valid. - if self._update_settings: - self.check_update() - - # Run workflow's entry function/method - func(self) - - # Set last version run to current version after a successful - # run - self.set_last_version() - - except Exception as err: - self.logger.exception(err) - if self.help_url: - self.logger.info('for assistance, see: %s', self.help_url) - - if not sys.stdout.isatty(): # Show error in Alfred - if text_errors: - print(unicode(err).encode('utf-8'), end='') - else: - self._items = [] - if self._name: - name = self._name - elif self._bundleid: # pragma: no cover - name = self._bundleid - else: # pragma: no cover - name = os.path.dirname(__file__) - self.add_item("Error in workflow '%s'" % name, - unicode(err), - icon=ICON_ERROR) - self.send_feedback() - return 1 - - finally: - self.logger.debug('---------- finished in %0.3fs ----------', - time.time() - start) - - return 0 - - # Alfred feedback methods ------------------------------------------ - - def add_item(self, title, subtitle='', modifier_subtitles=None, arg=None, - autocomplete=None, valid=False, uid=None, icon=None, - icontype=None, type=None, largetext=None, copytext=None, - quicklookurl=None): - """Add an item to be output to Alfred. - - :param title: Title shown in Alfred - :type title: ``unicode`` - :param subtitle: Subtitle shown in Alfred - :type subtitle: ``unicode`` - :param modifier_subtitles: Subtitles shown when modifier - (CMD, OPT etc.) is pressed. Use a ``dict`` with the lowercase - keys ``cmd``, ``ctrl``, ``shift``, ``alt`` and ``fn`` - :type modifier_subtitles: ``dict`` - :param arg: Argument passed by Alfred as ``{query}`` when item is - actioned - :type arg: ``unicode`` - :param autocomplete: Text expanded in Alfred when item is TABbed - :type autocomplete: ``unicode`` - :param valid: Whether or not item can be actioned - :type valid: ``Boolean`` - :param uid: Used by Alfred to remember/sort items - :type uid: ``unicode`` - :param icon: Filename of icon to use - :type icon: ``unicode`` - :param icontype: Type of icon. Must be one of ``None`` , ``'filetype'`` - or ``'fileicon'``. Use ``'filetype'`` when ``icon`` is a filetype - such as ``'public.folder'``. Use ``'fileicon'`` when you wish to - use the icon of the file specified as ``icon``, e.g. - ``icon='/Applications/Safari.app', icontype='fileicon'``. - Leave as `None` if ``icon`` points to an actual - icon file. - :type icontype: ``unicode`` - :param type: Result type. Currently only ``'file'`` is supported - (by Alfred). This will tell Alfred to enable file actions for - this item. - :type type: ``unicode`` - :param largetext: Text to be displayed in Alfred's large text box - if user presses CMD+L on item. - :type largetext: ``unicode`` - :param copytext: Text to be copied to pasteboard if user presses - CMD+C on item. - :type copytext: ``unicode`` - :param quicklookurl: URL to be displayed using Alfred's Quick Look - feature (tapping ``SHIFT`` or ``⌘+Y`` on a result). - :type quicklookurl: ``unicode`` - :returns: :class:`Item` instance - - See :ref:`icons` for a list of the supported system icons. - - .. note:: - - Although this method returns an :class:`Item` instance, you don't - need to hold onto it or worry about it. All generated :class:`Item` - instances are also collected internally and sent to Alfred when - :meth:`send_feedback` is called. - - The generated :class:`Item` is only returned in case you want to - edit it or do something with it other than send it to Alfred. - - """ - item = self.item_class(title, subtitle, modifier_subtitles, arg, - autocomplete, valid, uid, icon, icontype, type, - largetext, copytext, quicklookurl) - self._items.append(item) - return item - - def send_feedback(self): - """Print stored items to console/Alfred as XML.""" - root = ET.Element('items') - for item in self._items: - root.append(item.elem) - sys.stdout.write('\n') - sys.stdout.write(ET.tostring(root).encode('utf-8')) - sys.stdout.flush() - - #################################################################### - # Updating methods - #################################################################### - - @property - def first_run(self): - """Return ``True`` if it's the first time this version has run. - - .. versionadded:: 1.9.10 - - Raises a :class:`ValueError` if :attr:`version` isn't set. - - """ - if not self.version: - raise ValueError('No workflow version set') - - if not self.last_version_run: - return True - - return self.version != self.last_version_run - - @property - def last_version_run(self): - """Return version of last version to run (or ``None``). - - .. versionadded:: 1.9.10 - - :returns: :class:`~workflow.update.Version` instance - or ``None`` - - """ - if self._last_version_run is UNSET: - - version = self.settings.get('__workflow_last_version') - if version: - from update import Version - version = Version(version) - - self._last_version_run = version - - self.logger.debug('last run version: %s', self._last_version_run) - - return self._last_version_run - - def set_last_version(self, version=None): - """Set :attr:`last_version_run` to current version. - - .. versionadded:: 1.9.10 - - :param version: version to store (default is current version) - :type version: :class:`~workflow.update.Version` instance - or ``unicode`` - :returns: ``True`` if version is saved, else ``False`` - - """ - if not version: - if not self.version: - self.logger.warning( - "Can't save last version: workflow has no version") - return False - - version = self.version - - if isinstance(version, basestring): - from update import Version - version = Version(version) - - self.settings['__workflow_last_version'] = str(version) - - self.logger.debug('set last run version: %s', version) - - return True - - @property - def update_available(self): - """Whether an update is available. - - .. versionadded:: 1.9 - - See :ref:`guide-updates` in the :ref:`user-manual` for detailed - information on how to enable your workflow to update itself. - - :returns: ``True`` if an update is available, else ``False`` - - """ - key = '__workflow_latest_version' - # Create a new workflow object to ensure standard serialiser - # is used (update.py is called without the user's settings) - status = Workflow().cached_data(key, max_age=0) - - # self.logger.debug('update status: %r', status) - if not status or not status.get('available'): - return False - - return status['available'] - - @property - def prereleases(self): - """Whether workflow should update to pre-release versions. - - .. versionadded:: 1.16 - - :returns: ``True`` if pre-releases are enabled with the :ref:`magic - argument ` or the ``update_settings`` dict, else - ``False``. - - """ - if self._update_settings.get('prereleases'): - return True - - return self.settings.get('__workflow_prereleases') or False - - def check_update(self, force=False): - """Call update script if it's time to check for a new release. - - .. versionadded:: 1.9 - - The update script will be run in the background, so it won't - interfere in the execution of your workflow. - - See :ref:`guide-updates` in the :ref:`user-manual` for detailed - information on how to enable your workflow to update itself. - - :param force: Force update check - :type force: ``Boolean`` - - """ - key = '__workflow_latest_version' - frequency = self._update_settings.get('frequency', - DEFAULT_UPDATE_FREQUENCY) - - if not force and not self.settings.get('__workflow_autoupdate', True): - self.logger.debug('Auto update turned off by user') - return - - # Check for new version if it's time - if (force or not self.cached_data_fresh(key, frequency * 86400)): - - repo = self._update_settings['github_slug'] - # version = self._update_settings['version'] - version = str(self.version) - - from background import run_in_background - - # update.py is adjacent to this file - update_script = os.path.join(os.path.dirname(__file__), - b'update.py') - - cmd = ['/usr/bin/python', update_script, 'check', repo, version] - - if self.prereleases: - cmd.append('--prereleases') - - self.logger.info('checking for update ...') - - run_in_background('__workflow_update_check', cmd) - - else: - self.logger.debug('update check not due') - - def start_update(self): - """Check for update and download and install new workflow file. - - .. versionadded:: 1.9 - - See :ref:`guide-updates` in the :ref:`user-manual` for detailed - information on how to enable your workflow to update itself. - - :returns: ``True`` if an update is available and will be - installed, else ``False`` - - """ - import update - - repo = self._update_settings['github_slug'] - # version = self._update_settings['version'] - version = str(self.version) - - if not update.check_update(repo, version, self.prereleases): - return False - - from background import run_in_background - - # update.py is adjacent to this file - update_script = os.path.join(os.path.dirname(__file__), - b'update.py') - - cmd = ['/usr/bin/python', update_script, 'install', repo, version] - - if self.prereleases: - cmd.append('--prereleases') - - self.logger.debug('downloading update ...') - run_in_background('__workflow_update_install', cmd) - - return True - - #################################################################### - # Keychain password storage methods - #################################################################### - - def save_password(self, account, password, service=None): - """Save account credentials. - - If the account exists, the old password will first be deleted - (Keychain throws an error otherwise). - - If something goes wrong, a :class:`KeychainError` exception will - be raised. - - :param account: name of the account the password is for, e.g. - "Pinboard" - :type account: ``unicode`` - :param password: the password to secure - :type password: ``unicode`` - :param service: Name of the service. By default, this is the - workflow's bundle ID - :type service: ``unicode`` - - """ - if not service: - service = self.bundleid - - try: - self._call_security('add-generic-password', service, account, - '-w', password) - self.logger.debug('saved password : %s:%s', service, account) - - except PasswordExists: - self.logger.debug('password exists : %s:%s', service, account) - current_password = self.get_password(account, service) - - if current_password == password: - self.logger.debug('password unchanged') - - else: - self.delete_password(account, service) - self._call_security('add-generic-password', service, - account, '-w', password) - self.logger.debug('save_password : %s:%s', service, account) - - def get_password(self, account, service=None): - """Retrieve the password saved at ``service/account``. - - Raise :class:`PasswordNotFound` exception if password doesn't exist. - - :param account: name of the account the password is for, e.g. - "Pinboard" - :type account: ``unicode`` - :param service: Name of the service. By default, this is the workflow's - bundle ID - :type service: ``unicode`` - :returns: account password - :rtype: ``unicode`` - - """ - if not service: - service = self.bundleid - - output = self._call_security('find-generic-password', service, - account, '-g') - - # Parsing of `security` output is adapted from python-keyring - # by Jason R. Coombs - # https://pypi.python.org/pypi/keyring - m = re.search( - r'password:\s*(?:0x(?P[0-9A-F]+)\s*)?(?:"(?P.*)")?', - output) - - if m: - groups = m.groupdict() - h = groups.get('hex') - password = groups.get('pw') - if h: - password = unicode(binascii.unhexlify(h), 'utf-8') - - self.logger.debug('got password : %s:%s', service, account) - - return password - - def delete_password(self, account, service=None): - """Delete the password stored at ``service/account``. - - Raise :class:`PasswordNotFound` if account is unknown. - - :param account: name of the account the password is for, e.g. - "Pinboard" - :type account: ``unicode`` - :param service: Name of the service. By default, this is the workflow's - bundle ID - :type service: ``unicode`` - - """ - if not service: - service = self.bundleid - - self._call_security('delete-generic-password', service, account) - - self.logger.debug('deleted password : %s:%s', service, account) - - #################################################################### - # Methods for workflow:* magic args - #################################################################### - - def _register_default_magic(self): - """Register the built-in magic arguments.""" - # TODO: refactor & simplify - # Wrap callback and message with callable - def callback(func, msg): - def wrapper(): - func() - return msg - - return wrapper - - self.magic_arguments['delcache'] = callback(self.clear_cache, - 'Deleted workflow cache') - self.magic_arguments['deldata'] = callback(self.clear_data, - 'Deleted workflow data') - self.magic_arguments['delsettings'] = callback( - self.clear_settings, 'Deleted workflow settings') - self.magic_arguments['reset'] = callback(self.reset, - 'Reset workflow') - self.magic_arguments['openlog'] = callback(self.open_log, - 'Opening workflow log file') - self.magic_arguments['opencache'] = callback( - self.open_cachedir, 'Opening workflow cache directory') - self.magic_arguments['opendata'] = callback( - self.open_datadir, 'Opening workflow data directory') - self.magic_arguments['openworkflow'] = callback( - self.open_workflowdir, 'Opening workflow directory') - self.magic_arguments['openterm'] = callback( - self.open_terminal, 'Opening workflow root directory in Terminal') - - # Diacritic folding - def fold_on(): - self.settings['__workflow_diacritic_folding'] = True - return 'Diacritics will always be folded' - - def fold_off(): - self.settings['__workflow_diacritic_folding'] = False - return 'Diacritics will never be folded' - - def fold_default(): - if '__workflow_diacritic_folding' in self.settings: - del self.settings['__workflow_diacritic_folding'] - return 'Diacritics folding reset' - - self.magic_arguments['foldingon'] = fold_on - self.magic_arguments['foldingoff'] = fold_off - self.magic_arguments['foldingdefault'] = fold_default - - # Updates - def update_on(): - self.settings['__workflow_autoupdate'] = True - return 'Auto update turned on' - - def update_off(): - self.settings['__workflow_autoupdate'] = False - return 'Auto update turned off' - - def prereleases_on(): - self.settings['__workflow_prereleases'] = True - return 'Prerelease updates turned on' - - def prereleases_off(): - self.settings['__workflow_prereleases'] = False - return 'Prerelease updates turned off' - - def do_update(): - if self.start_update(): - return 'Downloading and installing update ...' - else: - return 'No update available' - - self.magic_arguments['autoupdate'] = update_on - self.magic_arguments['noautoupdate'] = update_off - self.magic_arguments['prereleases'] = prereleases_on - self.magic_arguments['noprereleases'] = prereleases_off - self.magic_arguments['update'] = do_update - - # Help - def do_help(): - if self.help_url: - self.open_help() - return 'Opening workflow help URL in browser' - else: - return 'Workflow has no help URL' - - def show_version(): - if self.version: - return 'Version: {0}'.format(self.version) - else: - return 'This workflow has no version number' - - def list_magic(): - """Display all available magic args in Alfred.""" - isatty = sys.stderr.isatty() - for name in sorted(self.magic_arguments.keys()): - if name == 'magic': - continue - arg = self.magic_prefix + name - self.logger.debug(arg) - - if not isatty: - self.add_item(arg, icon=ICON_INFO) - - if not isatty: - self.send_feedback() - - self.magic_arguments['help'] = do_help - self.magic_arguments['magic'] = list_magic - self.magic_arguments['version'] = show_version - - def clear_cache(self, filter_func=lambda f: True): - """Delete all files in workflow's :attr:`cachedir`. - - :param filter_func: Callable to determine whether a file should be - deleted or not. ``filter_func`` is called with the filename - of each file in the data directory. If it returns ``True``, - the file will be deleted. - By default, *all* files will be deleted. - :type filter_func: ``callable`` - """ - self._delete_directory_contents(self.cachedir, filter_func) - - def clear_data(self, filter_func=lambda f: True): - """Delete all files in workflow's :attr:`datadir`. - - :param filter_func: Callable to determine whether a file should be - deleted or not. ``filter_func`` is called with the filename - of each file in the data directory. If it returns ``True``, - the file will be deleted. - By default, *all* files will be deleted. - :type filter_func: ``callable`` - """ - self._delete_directory_contents(self.datadir, filter_func) - - def clear_settings(self): - """Delete workflow's :attr:`settings_path`.""" - if os.path.exists(self.settings_path): - os.unlink(self.settings_path) - self.logger.debug('deleted : %r', self.settings_path) - - def reset(self): - """Delete workflow settings, cache and data. - - File :attr:`settings ` and directories - :attr:`cache ` and :attr:`data ` are deleted. - - """ - self.clear_cache() - self.clear_data() - self.clear_settings() - - def open_log(self): - """Open :attr:`logfile` in default app (usually Console.app).""" - subprocess.call(['open', self.logfile]) - - def open_cachedir(self): - """Open the workflow's :attr:`cachedir` in Finder.""" - subprocess.call(['open', self.cachedir]) - - def open_datadir(self): - """Open the workflow's :attr:`datadir` in Finder.""" - subprocess.call(['open', self.datadir]) - - def open_workflowdir(self): - """Open the workflow's :attr:`workflowdir` in Finder.""" - subprocess.call(['open', self.workflowdir]) - - def open_terminal(self): - """Open a Terminal window at workflow's :attr:`workflowdir`.""" - subprocess.call(['open', '-a', 'Terminal', - self.workflowdir]) - - def open_help(self): - """Open :attr:`help_url` in default browser.""" - subprocess.call(['open', self.help_url]) - - return 'Opening workflow help URL in browser' - - #################################################################### - # Helper methods - #################################################################### - - def decode(self, text, encoding=None, normalization=None): - """Return ``text`` as normalised unicode. - - If ``encoding`` and/or ``normalization`` is ``None``, the - ``input_encoding``and ``normalization`` parameters passed to - :class:`Workflow` are used. - - :param text: string - :type text: encoded or Unicode string. If ``text`` is already a - Unicode string, it will only be normalised. - :param encoding: The text encoding to use to decode ``text`` to - Unicode. - :type encoding: ``unicode`` or ``None`` - :param normalization: The nomalisation form to apply to ``text``. - :type normalization: ``unicode`` or ``None`` - :returns: decoded and normalised ``unicode`` - - :class:`Workflow` uses "NFC" normalisation by default. This is the - standard for Python and will work well with data from the web (via - :mod:`~workflow.web` or :mod:`json`). - - macOS, on the other hand, uses "NFD" normalisation (nearly), so data - coming from the system (e.g. via :mod:`subprocess` or - :func:`os.listdir`/:mod:`os.path`) may not match. You should either - normalise this data, too, or change the default normalisation used by - :class:`Workflow`. - - """ - encoding = encoding or self._input_encoding - normalization = normalization or self._normalizsation - if not isinstance(text, unicode): - text = unicode(text, encoding) - return unicodedata.normalize(normalization, text) - - def fold_to_ascii(self, text): - """Convert non-ASCII characters to closest ASCII equivalent. - - .. versionadded:: 1.3 - - .. note:: This only works for a subset of European languages. - - :param text: text to convert - :type text: ``unicode`` - :returns: text containing only ASCII characters - :rtype: ``unicode`` - - """ - if isascii(text): - return text - text = ''.join([ASCII_REPLACEMENTS.get(c, c) for c in text]) - return unicode(unicodedata.normalize('NFKD', - text).encode('ascii', 'ignore')) - - def dumbify_punctuation(self, text): - """Convert non-ASCII punctuation to closest ASCII equivalent. - - This method replaces "smart" quotes and n- or m-dashes with their - workaday ASCII equivalents. This method is currently not used - internally, but exists as a helper method for workflow authors. - - .. versionadded: 1.9.7 - - :param text: text to convert - :type text: ``unicode`` - :returns: text with only ASCII punctuation - :rtype: ``unicode`` - - """ - if isascii(text): - return text - - text = ''.join([DUMB_PUNCTUATION.get(c, c) for c in text]) - return text - - def _delete_directory_contents(self, dirpath, filter_func): - """Delete all files in a directory. - - :param dirpath: path to directory to clear - :type dirpath: ``unicode`` or ``str`` - :param filter_func function to determine whether a file shall be - deleted or not. - :type filter_func ``callable`` - - """ - if os.path.exists(dirpath): - for filename in os.listdir(dirpath): - if not filter_func(filename): - continue - path = os.path.join(dirpath, filename) - if os.path.isdir(path): - shutil.rmtree(path) - else: - os.unlink(path) - self.logger.debug('deleted : %r', path) - - def _load_info_plist(self): - """Load workflow info from ``info.plist``.""" - # info.plist should be in the directory above this one - self._info = plistlib.readPlist(self.workflowfile('info.plist')) - self._info_loaded = True - - def _create(self, dirpath): - """Create directory `dirpath` if it doesn't exist. - - :param dirpath: path to directory - :type dirpath: ``unicode`` - :returns: ``dirpath`` argument - :rtype: ``unicode`` - - """ - if not os.path.exists(dirpath): - os.makedirs(dirpath) - return dirpath - - def _call_security(self, action, service, account, *args): - """Call ``security`` CLI program that provides access to keychains. - - May raise `PasswordNotFound`, `PasswordExists` or `KeychainError` - exceptions (the first two are subclasses of `KeychainError`). - - :param action: The ``security`` action to call, e.g. - ``add-generic-password`` - :type action: ``unicode`` - :param service: Name of the service. - :type service: ``unicode`` - :param account: name of the account the password is for, e.g. - "Pinboard" - :type account: ``unicode`` - :param password: the password to secure - :type password: ``unicode`` - :param *args: list of command line arguments to be passed to - ``security`` - :type *args: `list` or `tuple` - :returns: ``(retcode, output)``. ``retcode`` is an `int`, ``output`` a - ``unicode`` string. - :rtype: `tuple` (`int`, ``unicode``) - - """ - cmd = ['security', action, '-s', service, '-a', account] + list(args) - p = subprocess.Popen(cmd, stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - stdout, _ = p.communicate() - if p.returncode == 44: # password does not exist - raise PasswordNotFound() - elif p.returncode == 45: # password already exists - raise PasswordExists() - elif p.returncode > 0: - err = KeychainError('Unknown Keychain error : %s' % stdout) - err.retcode = p.returncode - raise err - return stdout.strip().decode('utf-8') diff --git a/src/lib/xp_workflow/.alfredversionchecked b/src/lib/xp_workflow/.alfredversionchecked deleted file mode 100644 index e69de29..0000000 diff --git a/src/lib/xp_workflow/__init__.py b/src/lib/xp_workflow/__init__.py deleted file mode 100644 index 3e4e1df..0000000 --- a/src/lib/xp_workflow/__init__.py +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/env python3 - -"""A helper library for `Alfred `_ workflows.""" -import os - -# Workflow objects -from .workflow import Workflow, manager, Variables - -# Exceptions -from .workflow import PasswordNotFound, KeychainError - -# Icons -from .workflow import ( - ICON_ACCOUNT, - ICON_BURN, - ICON_CLOCK, - ICON_COLOR, - ICON_COLOUR, - ICON_EJECT, - ICON_ERROR, - ICON_FAVORITE, - ICON_FAVOURITE, - ICON_GROUP, - ICON_HELP, - ICON_HOME, - ICON_INFO, - ICON_NETWORK, - ICON_NOTE, - ICON_SETTINGS, - ICON_SWIRL, - ICON_SWITCH, - ICON_SYNC, - ICON_TRASH, - ICON_USER, - ICON_WEB, -) - -# Filter matching rules -from .workflow import ( - MATCH_ALL, - MATCH_ALLCHARS, - MATCH_ATOM, - MATCH_CAPITALS, - MATCH_INITIALS, - MATCH_INITIALS_CONTAIN, - MATCH_INITIALS_STARTSWITH, - MATCH_STARTSWITH, - MATCH_SUBSTRING, -) - -# pylint: disable=consider-using-with -__version__ = open( - os.path.join(os.path.dirname(__file__), "version"), encoding="utf-8" -).read() -__title__ = "Alpynist" -__author__ = "Arthur Pinheiro" -__license__ = "MIT" -__copyright__ = "Copyright 2022 Arthur Pinheiro" - -__all__ = [ - "Variables", - "Workflow", - "manager", - "PasswordNotFound", - "KeychainError", - "ICON_ACCOUNT", - "ICON_BURN", - "ICON_CLOCK", - "ICON_COLOR", - "ICON_COLOUR", - "ICON_EJECT", - "ICON_ERROR", - "ICON_FAVORITE", - "ICON_FAVOURITE", - "ICON_GROUP", - "ICON_HELP", - "ICON_HOME", - "ICON_INFO", - "ICON_NETWORK", - "ICON_NOTE", - "ICON_SETTINGS", - "ICON_SWIRL", - "ICON_SWITCH", - "ICON_SYNC", - "ICON_TRASH", - "ICON_USER", - "ICON_WEB", - "MATCH_ALL", - "MATCH_ALLCHARS", - "MATCH_ATOM", - "MATCH_CAPITALS", - "MATCH_INITIALS", - "MATCH_INITIALS_CONTAIN", - "MATCH_INITIALS_STARTSWITH", - "MATCH_STARTSWITH", - "MATCH_SUBSTRING", -] diff --git a/src/lib/xp_workflow/background.py b/src/lib/xp_workflow/background.py deleted file mode 100644 index 2035c4b..0000000 --- a/src/lib/xp_workflow/background.py +++ /dev/null @@ -1,284 +0,0 @@ -#!/usr/bin/env python3 - -"""This module provides an API to run commands in background processes. - -Combine with the :ref:`caching API ` to work from cached data -while you fetch fresh data in the background. - -See :ref:`the User Manual ` for more information -and examples. -""" - -import os -import pickle -import signal -import subprocess -import sys - -from workflow import Workflow - -__all__ = ["is_running", "run_in_background"] - -_wf = None - - -def wf(): - """Lazy `Workflow` object.""" - global _wf - if _wf is None: - _wf = Workflow() - return _wf - - -def _log(): - return wf().logger - - -def _arg_cache(name): - """Return path to pickle cache file for arguments. - - :param name: name of task - :type name: ``str`` - :returns: Path to cache file - :rtype: ``str`` filepath - - """ - return wf().cachefile(name + ".argcache") - - -def _pid_file(name): - """Return path to PID file for ``name``. - - :param name: name of task - :type name: ``str`` - :returns: Path to PID file for task - :rtype: ``str`` filepath - - """ - return wf().cachefile(name + ".pid") - - -def _process_exists(pid): - """Check if a process with PID ``pid`` exists. - - :param pid: PID to check - :type pid: ``int`` - :returns: ``True`` if process exists, else ``False`` - :rtype: ``Boolean`` - - """ - try: - os.kill(pid, 0) - except OSError: # not running - return False - return True - - -def _job_pid(name): - """Get PID of job or `None` if job does not exist. - - Args: - name (str): Name of job. - - Returns: - int: PID of job process (or `None` if job doesn't exist). - """ - pidfile = _pid_file(name) - - if os.path.exists(pidfile): - with open(pidfile, "rb") as f: - read = f.read() - pid = int.from_bytes(read, sys.byteorder) - - if _process_exists(pid): - return pid - - os.unlink(pidfile) - return None - - -def is_running(name): - """Test whether task ``name`` is currently running. - - :param name: name of task - :type name: str - :returns: ``True`` if task with name ``name`` is running, else ``False`` - :rtype: bool - - """ - if _job_pid(name) is not None: - return True - - return False - - -def _background( - pidfile, stdin="/dev/null", stdout="/dev/null", stderr="/dev/null" -): # pragma: no cover - """Fork the current process into a background daemon. - - :param pidfile: file to write PID of daemon process to. - :type pidfile: filepath - :param stdin: where to read input - :type stdin: filepath - :param stdout: where to write stdout output - :type stdout: filepath - :param stderr: where to write stderr output - :type stderr: filepath - - """ - - def _fork_and_exit_parent(errmsg, wait=False, write=False): - try: - pid = os.fork() - if pid > 0: - if write: # write PID of child process to `pidfile` - tmp = pidfile + ".tmp" - with open(tmp, "wb") as f: - f.write(pid.to_bytes(4, sys.byteorder)) - os.rename(tmp, pidfile) - if wait: # wait for child process to exit - os.waitpid(pid, 0) - os._exit(0) - except OSError as err: - _log().critical("%s: (%d) %s", errmsg, err.errno, err.strerror) - raise err - - # Do first fork and wait for second fork to finish. - _fork_and_exit_parent("fork #1 failed", wait=True) - - # Decouple from parent environment. - os.chdir(wf().workflowdir) - os.setsid() - - # Do second fork and write PID to pidfile. - _fork_and_exit_parent("fork #2 failed", write=True) - - # Now I am a daemon! - # Redirect standard file descriptors. - with open(stdin, "r", 1, encoding="utf-8") as stdin_fd: - if hasattr(sys.stdin, "fileno"): - os.dup2(stdin_fd.fileno(), sys.stdin.fileno()) - - with open(stdout, "a+", 1, encoding="utf-8") as stdout_fd: - if hasattr(sys.stdout, "fileno"): - os.dup2(stdout_fd.fileno(), sys.stdout.fileno()) - - with open(stderr, "a+", 1, encoding="utf-8") as stderr_fd: - if hasattr(sys.stderr, "fileno"): - os.dup2(stderr_fd.fileno(), sys.stderr.fileno()) - - -def kill(name, sig=signal.SIGTERM): - """Send a signal to job ``name`` via :func:`os.kill`. - - Args: - name (str): Name of the job - sig (int, optional): Signal to send (default: SIGTERM) - - Returns: - bool: `False` if job isn't running, `True` if signal was sent. - """ - pid = _job_pid(name) - if pid is None: - return False - - os.kill(pid, sig) - return True - - -def run_in_background(name, args, **kwargs): - r"""Cache arguments then call this script again via :func:`subprocess.run`. - - :param name: name of job - :type name: str - :param args: arguments passed as first argument to :func:`subprocess.run` - :param \**kwargs: keyword arguments to :func:`subprocess.run` - :returns: exit code of sub-process - :rtype: int - - When you call this function, it caches its arguments and then calls - ``background.py`` in a subprocess. The Python subprocess will load the - cached arguments, fork into the background, and then run the command you - specified. - - This function will return as soon as the ``background.py`` subprocess has - forked, returning the exit code of *that* process (i.e. not of the command - you're trying to run). - - If that process fails, an error will be written to the log file. - - If a process is already running under the same name, this function will - return immediately and will not run the specified command. - - """ - if is_running(name): - _log().info("[%s] job already running", name) - return None - - argcache = _arg_cache(name) - - # Cache arguments - with open(argcache, "wb") as f: - pickle.dump({"args": args, "kwargs": kwargs}, f) - _log().debug("[%s] command cached: %s", name, argcache) - - # Call this script - cmd = ["/usr/bin/python3", "-m", "workflow.background", name] - _log().debug("[%s] passing job to background runner: %r", name, cmd) - retcode = subprocess.run(cmd, check=True).returncode - - if retcode: # pragma: no cover - _log().error("[%s] background runner failed with %d", name, retcode) - else: - _log().debug("[%s] background job started", name) - - return retcode - - -def main(wf): # pragma: no cover - """Run command in a background process. - - Load cached arguments, fork into background, then call - :meth:`subprocess.run` with cached arguments. - - """ - log = wf.logger - name = wf.args[0] - argcache = _arg_cache(name) - if not os.path.exists(argcache): - msg = f"[{name}] command cache not found: {argcache}" - log.critical(msg) - raise IOError(msg) - - # Fork to background and run command - pidfile = _pid_file(name) - _background(pidfile) - - # Load cached arguments - with open(argcache, "rb") as f: - data = pickle.load(f) - - # Cached arguments - args = data["args"] - kwargs = data["kwargs"] - - # Delete argument cache file - os.unlink(argcache) - - try: - # Run the command - log.debug("[%s] running command: %r", name, args) - - retcode = subprocess.run(args, **kwargs, check=True).returncode - - if retcode: - log.error("[%s] command failed with status %d", name, retcode) - finally: - os.unlink(pidfile) - - log.debug("[%s] job complete", name) - - -if __name__ == "__main__": # pragma: no cover - wf().run(main) diff --git a/src/lib/xp_workflow/notificator b/src/lib/xp_workflow/notificator deleted file mode 100755 index 1d5d646..0000000 --- a/src/lib/xp_workflow/notificator +++ /dev/null @@ -1,169 +0,0 @@ -#!/bin/zsh - -#################################################### -### Created by Vítor Galvão ### -### Find the latest version at: ### -### https://github.com/vitorgalvao/notificator ### -#################################################### - -readonly program="$(basename "${0}")" - -# Helpers -function show_notification { - /usr/bin/open "${app}" --args "${notificator_message}" "${notificator_title}" "${notificator_subtitle}" "${notificator_sound}" -} - -function make_icns { - # Setup - local -r file="${1}" - local -r tmp_dir="$(/usr/bin/mktemp -d)" - local -r icon="${tmp_dir}/icon.icns" - local -r iconset="${tmp_dir}/icon.iconset" - /bin/mkdir "${iconset}" - - # Create iconset - for size in {16,32,64,128,256,512}; do - /usr/bin/sips --resampleHeightWidth "${size}" "${size}" "${file}" --out "${iconset}/icon_${size}x${size}.png" &> /dev/null - /usr/bin/sips --resampleHeightWidth "$((size * 2))" "$((size * 2))" "${file}" --out "${iconset}/icon_${size}x${size}@2x.png" &> /dev/null - done - - # Convert to icns - /usr/bin/iconutil --convert icns "${iconset}" --output "${icon}" - - # Clean up and return path to icns - /bin/rm -rf "${iconset}" - echo "${icon}" -} - -function usage { - echo " - Trigger macOS notifications from Alfred, using the Workflow icon - - Usage: - ${program} --message [options] - - Options: - -m, --message Message text - -t, --title Title text - -s, --subtitle Subtitle text - -p, --sound Sound name (from /System/Library/Sounds) - -h, --help Show this help - " | sed -E 's/^ {4}//' -} - -# Options -args=() -while [[ "${1}" ]]; do - case "${1}" in - -h | --help) - usage - exit 0 - ;; - -m | --message) - readonly notificator_message="${2}" - shift - ;; - -t | --title) - readonly notificator_title="${2}" - shift - ;; - -s | --subtitle) - readonly notificator_subtitle="${2}" - shift - ;; - -p | --sound) - readonly notificator_sound="${2}" - shift - ;; - --) - shift - args+=("${@}") - break - ;; - -*) - echo "Unrecognised option: ${1}" - exit 1 - ;; - *) - args+=("${1}") - ;; - esac - shift -done -set -- "${args[@]}" - -# Check for required arguments -if [[ -z "${notificator_message}" ]]; then - echo 'A message is mandatory! Aborting…' >&2 - exit 1 -fi - -readonly bundle_id="$(tr -cd '[:alnum:]._-' <<< "${alfred_workflow_bundleid}")" -readonly icon="${alfred_preferences}/workflows/${alfred_workflow_uid}/icon.png" -readonly app="${alfred_workflow_cache}/Notificator.app" -readonly plist="${app}/Contents/Info.plist" - -# Exit early if Notificator exists and was modified fewer than 30 days ago -if [[ -e "${app}" && -n "$(find "${app}" -depth 0 -mtime -30)" ]]; then - show_notification - exit 0 -fi - -# Pre-build checks -if [[ -z "${bundle_id}" ]]; then - echo "Workflow is missing the bundle identifier! Aborting…" >&2 - exit 1 -fi - -if [[ ! -f "${icon}" ]]; then - echo "Workflow is missing the icon! Aborting…" >&2 - exit 1 -fi - -# Build Notificator -readonly jxa_script=' - // Build argv/argc in a way that can be used from the applet inside the app bundle - ObjC.import("Foundation") - const args = $.NSProcessInfo.processInfo.arguments - const argv = [] - const argc = args.count - for (let i = 0; i < argc; i++) { argv.push(ObjC.unwrap(args.objectAtIndex(i))) } - - // Notification script - const app = Application.currentApplication() - app.includeStandardAdditions = true - - if (argv.length < 2) { // We use "2" because the script will always see at least one argument: the applet itself - argv[1] = "Opening usage instructions…" - argv[2] = "Notificator is a command-line app" - argv[4] = "Funk" - - app.openLocation("https://github.com/vitorgalvao/notificator#usage") - } - - const message = argv[1] - const title = argv[2] - const subtitle = argv[3] - const sound = argv[4] - - const options = {} - if (title) options.withTitle = title - if (subtitle) options.subtitle = subtitle - if (sound) options.soundName = sound - - app.displayNotification(message, options) -' - -/bin/mkdir -p "${alfred_workflow_cache}" -/usr/bin/osacompile -l JavaScript -o "${app}" -e "${jxa_script}" &> /dev/null - -# Modify Notificator -/usr/libexec/PlistBuddy -c "add :CFBundleIdentifier string ${bundle_id}.notificator" "${plist}" -/usr/libexec/PlistBuddy -c 'add :LSUIElement string 1' "${plist}" -mv "$(make_icns "${icon}")" "${app}/Contents/Resources/applet.icns" - -# Redo signature -codesign --remove-signature "${app}" -codesign --sign - "${app}" - -show_notification diff --git a/src/lib/xp_workflow/notify.py b/src/lib/xp_workflow/notify.py deleted file mode 100644 index dfdbe0b..0000000 --- a/src/lib/xp_workflow/notify.py +++ /dev/null @@ -1,92 +0,0 @@ -#!/usr/bin/env python3 -# This module relies on Notificator created by Vítor Galvão -# See https://github.com/vitorgalvao/notificator - -""" -Post notifications via the macOS Notification Center. - -The main API is a single function, :func:`~workflow.notify.notify`. - -It works by copying a simple application to your workflow's cache -directory. -""" - -import os -import subprocess - -from . import workflow - -_wf = None -_log = None - - -#: Available system sounds from System Preferences > Sound > Sound Effects -SOUNDS = ( - "Basso", - "Blow", - "Bottle", - "Frog", - "Funk", - "Glass", - "Hero", - "Morse", - "Ping", - "Pop", - "Purr", - "Sosumi", - "Submarine", - "Tink", -) - - -def wf(): - """Return Workflow object for this module. - - Returns: - workflow.Workflow: Workflow object for current workflow. - """ - global _wf - if _wf is None: - _wf = workflow.Workflow() - return _wf - - -def log(): - """Return logger for this module. - - Returns: - logging.Logger: Logger for this module. - """ - global _log - if _log is None: - _log = wf().logger - return _log - - -def notify(title="", text="", sound=""): - """Post notification via Notify.app helper. - - Args: - title (str, optional): Notification title. - text (str, optional): Notification body text. - sound (str, optional): Name of sound to play. - - Raises: - ValueError: Raised if both ``title`` and ``text`` are empty. - - Returns: - bool: ``True`` if notification was posted, else ``False``. - """ - if text == "": - raise ValueError("A message is mandatory.") - - notificator = os.path.join(os.path.dirname(__file__), "notificator") - retcode = subprocess.run( - [notificator, "--title", title, "--message", text, "--sound", sound], check=True - ).returncode - - if retcode == 0: - return True - - log().error("Notificator exited with status %s", retcode) - return False diff --git a/src/lib/xp_workflow/update.py b/src/lib/xp_workflow/update.py deleted file mode 100644 index 87728ce..0000000 --- a/src/lib/xp_workflow/update.py +++ /dev/null @@ -1,544 +0,0 @@ -#!/usr/bin/env python3 - -"""Self-updating from GitHub. - -.. note:: - - This module is not intended to be used directly. Automatic updates - are controlled by the ``update_settings`` :class:`dict` passed to - :class:`~workflow.workflow.Workflow` objects. - -""" - -import json -import os -import re -import subprocess -import tempfile -from collections import defaultdict -from functools import total_ordering - -from . import workflow, web - - -RELEASES_BASE = "https://api.github.com/repos/{}/releases" -match_workflow = re.compile(r"\.alfred(\d+)?workflow$").search - -_wf = None - - -# pylint: disable=duplicate-code -def wf(): - """Lazy `Workflow` object.""" - global _wf - if _wf is None: - _wf = workflow.Workflow() - return _wf - - -@total_ordering -class Download: - """A workflow file that is available for download. - - Attributes: - url (str): URL of workflow file. - filename (str): Filename of workflow file. - version (Version): Semantic version of workflow. - prerelease (bool): Whether version is a pre-release. - alfred_version (Version): Minimum compatible version - of Alfred. - - """ - - @classmethod - def from_dict(cls, dl): - """Create a `Download` from a `dict`.""" - return cls( - url=dl["url"], - filename=dl["filename"], - version=Version(dl["version"]), - prerelease=dl["prerelease"], - ) - - @classmethod - def from_releases(cls, json_resp): - """Extract downloads from GitHub releases. - - Searches releases with semantic tags for assets with - file extension .alfredworkflow or .alfredXworkflow where - X is a number. - - Files are returned sorted by latest version first. Any - releases containing multiple files with the same (workflow) - extension are rejected as ambiguous. - - Args: - json_resp (str): JSON response from GitHub's releases endpoint. - - Returns: - list: Sequence of `Download`. - """ - releases = json.loads(json_resp) - downloads = [] - for release in releases: - tag = release["tag_name"] - dupes = defaultdict(int) - try: - version = Version(tag) - except ValueError as err: - wf().logger.debug('ignored release: bad version "%s": %s', tag, err) - continue - - dls = [] - for asset in release.get("assets", []): - url = asset.get("browser_download_url") - filename = os.path.basename(url) - is_match = match_workflow(filename) - if not is_match: - wf().logger.debug("unwanted file: %s", filename) - continue - - ext = is_match.group(0) - dupes[ext] = dupes[ext] + 1 - dls.append(Download(url, filename, version, release["prerelease"])) - - valid = True - for ext, n in list(dupes.items()): - if n > 1: - wf().logger.debug( - 'ignored release "%s": multiple assets with extension "%s"', - tag, - ext, - ) - valid = False - break - - if valid: - downloads.extend(dls) - - downloads.sort(reverse=True) - return downloads - - def __init__(self, url, filename, version, prerelease=False): - """Create a new Download. - - Args: - url (str): URL of workflow file. - filename (str): Filename of workflow file. - version (Version): Version of workflow. - prerelease (bool, optional): Whether version is - pre-release. Defaults to False. - - """ - if isinstance(version, str): - version = Version(version) - - self.url = url - self.filename = filename - self.version = version - self.prerelease = prerelease - - @property - def alfred_version(self): - """Minimum Alfred version based on filename extension.""" - is_match = match_workflow(self.filename) - if not is_match or not is_match.group(1): - return Version("0") - return Version(is_match.group(1)) - - @property - def dict(self): - """Convert `Download` to `dict`.""" - return dict( - url=self.url, - filename=self.filename, - version=str(self.version), - prerelease=self.prerelease, - ) - - def __str__(self): - """Format `Download` for printing.""" - return ( - "Download(" - "url={dl.url!r}, " - "filename={dl.filename!r}, " - "version={dl.version!r}, " - "prerelease={dl.prerelease!r}" - ")" - ).format(dl=self) - - def __repr__(self): - """Code-like representation of `Download`.""" - return str(self) - - def __eq__(self, other): - """Compare Downloads based on version numbers.""" - if ( - self.url != other.url - or self.filename != other.filename - or self.version != other.version - or self.prerelease != other.prerelease - ): - return False - return True - - def __ne__(self, other): - """Compare Downloads based on version numbers.""" - return not self.__eq__(other) - - def __lt__(self, other): - """Compare Downloads based on version numbers.""" - if self.version != other.version: - return self.version < other.version - return self.alfred_version < other.alfred_version - - -class Version: - """Mostly semantic versioning. - - The main difference to proper :ref:`semantic versioning ` - is that this implementation doesn't require a minor or patch version. - - Version strings may also be prefixed with "v", e.g.: - - >>> v = Version('v1.1.1') - >>> v.tuple - (1, 1, 1, '') - - >>> v = Version('2.0') - >>> v.tuple - (2, 0, 0, '') - - >>> Version('3.1-beta').tuple - (3, 1, 0, 'beta') - - >>> Version('1.0.1') > Version('0.0.1') - True - """ - - #: Match version and pre-release/build information in version strings - match_version = re.compile(r"([0-9][0-9\.]*)(.+)?").match - - def __init__(self, vstr): - """Create new `Version` object. - - Args: - vstr (basestring): Semantic version string. - """ - if not vstr: - raise ValueError(f"invalid version number: {vstr!r}") - - self.vstr = vstr - self.major = 0 - self.minor = 0 - self.patch = 0 - self.suffix = "" - self.build = "" - self._parse(vstr) - - def _parse(self, vstr): - vstr = str(vstr) - if vstr.startswith("v"): - is_match = self.match_version(vstr[1:]) - else: - is_match = self.match_version(vstr) - if not is_match: - raise ValueError("invalid version number: " + vstr) - - version, suffix = is_match.groups() - parts = self._parse_dotted_string(version) - self.major = parts.pop(0) - if parts: - self.minor = parts.pop(0) - if parts: - self.patch = parts.pop(0) - if parts: - raise ValueError("version number too long: " + vstr) - - if suffix: - # Build info - idx = suffix.find("+") - if idx > -1: - self.build = suffix[idx + 1 :] - suffix = suffix[:idx] - if suffix: - if not suffix.startswith("-"): - raise ValueError("suffix must start with - : " + suffix) - self.suffix = suffix[1:] - - @staticmethod - def _parse_dotted_string(string): - """Parse string ``s`` into list of ints and strings.""" - parsed = [] - parts = string.split(".") - for part in parts: - if part.isdigit(): - part = int(part) - parsed.append(part) - return parsed - - @property - def tuple(self): - """Version number as a tuple of major, minor, patch, pre-release.""" - return (self.major, self.minor, self.patch, self.suffix) - - def __lt__(self, other): - """Implement comparison.""" - if not isinstance(other, Version): - raise ValueError(f"not a Version instance: {other!r}") - if self.tuple[:3] < other.tuple[:3]: - return True - if self.tuple[:3] == other.tuple[:3]: # We need to compare suffixes - if self.suffix and not other.suffix: - return True - if other.suffix and not self.suffix: - return False - return self._parse_dotted_string(self.suffix) < self._parse_dotted_string( - other.suffix - ) - - return False - - def __eq__(self, other): - """Implement comparison.""" - if not isinstance(other, Version): - raise ValueError(f"not a Version instance: {other!r}") - return self.tuple == other.tuple - - def __ne__(self, other): - """Implement comparison.""" - return not self.__eq__(other) - - def __gt__(self, other): - """Implement comparison.""" - if not isinstance(other, Version): - raise ValueError(f"not a Version instance: {format(other)!r}") - return other.__lt__(self) - - def __le__(self, other): - """Implement comparison.""" - if not isinstance(other, Version): - raise ValueError(f"not a Version instance: {other!r}") - return not other.__lt__(self) - - def __ge__(self, other): - """Implement comparison.""" - return not self.__lt__(other) - - def __str__(self): - """Return semantic version string.""" - vstr = f"{self.major}.{self.minor}.{self.patch}" - if self.suffix: - vstr = f"{vstr}-{self.suffix}" - if self.build: - vstr = f"{vstr}+{self.build}" - return vstr - - def __repr__(self): - """Return 'code' representation of `Version`.""" - return f'Version("{str(self)}")' - - -def retrieve_download(dl): - """Saves a download to a temporary file and returns path. - - Args: - url (str): URL to .alfredworkflow file in GitHub repo - - Returns: - str: path to downloaded file - - """ - if not match_workflow(dl.filename): - raise ValueError(f"attachment not a workflow: {dl.filename}") - - path = os.path.join(tempfile.gettempdir(), dl.filename) - wf().logger.debug("downloading update from %r to %r ...", dl.url, path) - - r = web.get(dl.url) - r.raise_for_status() - r.save_to_path(path) - - return path - - -def build_api_url(repo): - """Generate releases URL from GitHub repo. - - Args: - repo (str): Repo name in form ``username/repo`` - - Returns: - str: URL to the API endpoint for the repo's releases - - """ - if len(repo.split("/")) != 2: - raise ValueError(f"invalid GitHub repo: {repo!r}") - - return RELEASES_BASE.format(repo) - - -def get_downloads(repo): - """Load available ``Download``s for GitHub repo. - - Args: - repo (str): GitHub repo to load releases for. - - Returns: - list: Sequence of `Download` contained in GitHub releases. - """ - url = build_api_url(repo) - - def _fetch(): - wf().logger.info("retrieving releases for %r ...", repo) - r = web.get(url) - r.raise_for_status() - return r.content - - key = "github-releases-" + repo.replace("/", "-") - json_resp = wf().cached_data(key, _fetch, max_age=60) - - return Download.from_releases(json_resp) - - -def latest_download(dls, alfred_version=None, prereleases=False): - """Return newest `Download`.""" - alfred_version = alfred_version or os.getenv("alfred_version") - version = None - if alfred_version: - version = Version(alfred_version) - - dls.sort(reverse=True) - for dl in dls: - if dl.prerelease and not prereleases: - wf().logger.debug("ignored prerelease: %s", dl.version) - continue - if version and dl.alfred_version > version: - wf().logger.debug( - "ignored incompatible (%s > %s): %s", - dl.alfred_version, - version, - dl.filename, - ) - continue - - wf().logger.debug("latest version: %s (%s)", dl.version, dl.filename) - return dl - - return None - - -def check_update(repo, current_version, prereleases=False, alfred_version=None): - """Check whether a newer release is available on GitHub. - - Args: - repo (str): ``username/repo`` for workflow's GitHub repo - current_version (str): the currently installed version of the - workflow. :ref:`Semantic versioning ` is required. - prereleases (bool): Whether to include pre-releases. - alfred_version (str): version of currently-running Alfred. - if empty, defaults to ``$alfred_version`` environment variable. - - Returns: - bool: ``True`` if an update is available, else ``False`` - - If an update is available, its version number and download URL will - be cached. - - """ - key = "__workflow_latest_version" - # data stored when no update is available - no_update = {"available": False, "download": None, "version": None} - current = Version(current_version) - - dls = get_downloads(repo) - if not dls: - wf().logger.warning("no valid downloads for %s", repo) - wf().cache_data(key, no_update) - return False - - wf().logger.info("%d download(s) for %s", len(dls), repo) - - dl = latest_download(dls, alfred_version, prereleases) - - if not dl: - wf().logger.warning("no compatible downloads for %s", repo) - wf().cache_data(key, no_update) - return False - - wf().logger.debug("latest=%r, installed=%r", dl.version, current) - - if dl.version > current: - wf().cache_data( - key, {"version": str(dl.version), "download": dl.dict, "available": True} - ) - return True - - wf().cache_data(key, no_update) - return False - - -def install_update(): - """If a newer release is available, download and install it. - - :returns: ``True`` if an update is installed, else ``False`` - - """ - key = "__workflow_latest_version" - # data stored when no update is available - no_update = {"available": False, "download": None, "version": None} - status = wf().cached_data(key, max_age=0) - - if not status or not status.get("available"): - wf().logger.info("no update available") - return False - - dl = status.get("download") - if not dl: - wf().logger.info("no download information") - return False - - path = retrieve_download(Download.from_dict(dl)) - - wf().logger.info("installing updated workflow ...") - subprocess.call(["open", path]) # nosec - - wf().cache_data(key, no_update) - return True - - -if __name__ == "__main__": # pragma: nocover - import sys - - prereleases = False - - def show_help(status=0): - """Print help message.""" - print("usage: update.py (check|install) [--prereleases] ") - sys.exit(status) - - argv = sys.argv[:] - if "-h" in argv or "--help" in argv: - show_help() - - if "--prereleases" in argv: - argv.remove("--prereleases") - prereleases = True - - if len(argv) != 4: - show_help(1) - - action = argv[1] - repo = argv[2] - version = argv[3] - - try: - if action == "check": - check_update(repo, version, prereleases) - elif action == "install": - install_update() - else: - show_help(1) - except Exception as err: # ensure traceback is in log file - wf().logger.exception(err) - raise err diff --git a/src/lib/xp_workflow/util.py b/src/lib/xp_workflow/util.py deleted file mode 100644 index 8ddb99e..0000000 --- a/src/lib/xp_workflow/util.py +++ /dev/null @@ -1,519 +0,0 @@ -#!/usr/bin/env python3 - -"""A selection of helper functions useful for building workflows.""" - -import atexit -import errno -import fcntl -import functools -import json -import os -import signal -import subprocess -import sys -import time -from collections import namedtuple -from contextlib import contextmanager -from threading import Event - - -# JXA scripts to call Alfred's API via the Scripting Bridge -# {app} is automatically replaced with "Alfred 3" or -# "com.runningwithcrayons.Alfred" depending on version. -# -# Open Alfred in search (regular) mode -JXA_SEARCH = "Application({app}).search({arg});" -# Open Alfred's File Actions on an argument -JXA_ACTION = "Application({app}).action({arg});" -# Open Alfred's navigation mode at path -JXA_BROWSE = "Application({app}).browse({arg});" -# Set the specified theme -JXA_SET_THEME = "Application({app}).setTheme({arg});" -# Call an External Trigger -JXA_TRIGGER = "Application({app}).runTrigger({arg}, {opts});" -# Save a variable to the workflow configuration sheet/info.plist -JXA_SET_CONFIG = "Application({app}).setConfiguration({arg}, {opts});" -# Delete a variable from the workflow configuration sheet/info.plist -JXA_UNSET_CONFIG = "Application({app}).removeConfiguration({arg}, {opts});" -# Tell Alfred to reload a workflow from disk -JXA_RELOAD_WORKFLOW = "Application({app}).reloadWorkflow({arg});" - - -class AcquisitionError(Exception): - """Raised if a lock cannot be acquired.""" - - -AppInfo = namedtuple("AppInfo", ["name", "path", "bundleid"]) -"""Information about an installed application. - -Returned by :func:`appinfo`. - -.. py:attribute:: name - - Name of the application, e.g. ``'Safari'``. - -.. py:attribute:: path - - Path to the application bundle, e.g. ``'/Applications/Safari.app'``. - -.. py:attribute:: bundleid - - Application's bundle ID, e.g. ``'com.apple.Safari'``. - -""" - - -def applescriptify(string): - """Escape string for insertion into an AppleScript string. - - Replaces ``"`` with `"& quote &"`. Use this function if you want - to insert a string into an AppleScript script: - - >>> applescriptify('g "python" test') - 'g " & quote & "python" & quote & "test' - - Args: - s (str): String to escape. - - Returns: - str: Escaped string. - - """ - return string.replace('"', '" & quote & "') - - -def run_applescript(script, *args, **kwargs): - """Execute an AppleScript script and return its output. - - Run AppleScript either by filepath or code. If ``script`` is a valid - filepath, that script will be run, otherwise ``script`` is treated - as code. - - Args: - script (str, optional): Filepath of script or code to run. - *args: Optional command-line arguments to pass to the script. - **kwargs: Pass ``lang`` to run a language other than AppleScript. - Any other keyword arguments are passed to :func:`~subprocess.run`. - - Returns: - str: Output of run command. - - """ - lang = "AppleScript" - if "lang" in kwargs: - lang = kwargs["lang"] - del kwargs["lang"] - - cmd = ["/usr/bin/osascript", "-l", lang] - - if os.path.exists(script): - cmd += [script] - else: - cmd += ["-e", script] - - cmd.extend(args) - - return subprocess.run(cmd, **kwargs, check=True, stdout=subprocess.PIPE).stdout - - -def run_jxa(script, *args): - """Execute a JXA script and return its output. - - Wrapper around :func:`run_applescript` that passes ``lang=JavaScript``. - - Args: - script (str): Filepath of script or code to run. - *args: Optional command-line arguments to pass to script. - - Returns: - str: Output of script. - - """ - return run_applescript(script, *args, lang="JavaScript") - - -def run_trigger(name, bundleid=None, arg=None): - """Call an Alfred External Trigger. - - If ``bundleid`` is not specified, the bundle ID of the calling - workflow is used. - - Args: - name (str): Name of External Trigger to call. - bundleid (str, optional): Bundle ID of workflow trigger belongs to. - arg (str, optional): Argument to pass to trigger. - - """ - bundleid = bundleid or os.getenv("alfred_workflow_bundleid") - appname = "com.runningwithcrayons.Alfred" - opts = {"inWorkflow": bundleid} - if arg: - opts["withArgument"] = arg - - script = JXA_TRIGGER.format( - app=json.dumps(appname), - arg=json.dumps(name), - opts=json.dumps(opts, sort_keys=True), - ) - - run_applescript(script, lang="JavaScript") - - -def set_theme(theme_name): - """Change Alfred's theme. - - Args: - theme_name (str): Name of theme Alfred should use. - - """ - appname = "com.runningwithcrayons.Alfred" - script = JXA_SET_THEME.format(app=json.dumps(appname), arg=json.dumps(theme_name)) - run_applescript(script, lang="JavaScript") - - -def set_config(name, value, bundleid=None, exportable=False): - """Set a workflow variable in ``info.plist``. - - If ``bundleid`` is not specified, the bundle ID of the calling - workflow is used. - - Args: - name (str): Name of variable to set. - value (str): Value to set variable to. - bundleid (str, optional): Bundle ID of workflow variable belongs to. - exportable (bool, optional): Whether variable should be marked - as exportable (Don't Export checkbox). - - """ - bundleid = bundleid or os.getenv("alfred_workflow_bundleid") - appname = "com.runningwithcrayons.Alfred" - opts = { - "toValue": value, - "inWorkflow": bundleid, - "exportable": exportable, - } - - script = JXA_SET_CONFIG.format( - app=json.dumps(appname), - arg=json.dumps(name), - opts=json.dumps(opts, sort_keys=True), - ) - - run_applescript(script, lang="JavaScript") - - -def unset_config(name, bundleid=None): - """Delete a workflow variable from ``info.plist``. - - If ``bundleid`` is not specified, the bundle ID of the calling - workflow is used. - - Args: - name (str): Name of variable to delete. - bundleid (str, optional): Bundle ID of workflow variable belongs to. - - """ - bundleid = bundleid or os.getenv("alfred_workflow_bundleid") - appname = "com.runningwithcrayons.Alfred" - opts = {"inWorkflow": bundleid} - - script = JXA_UNSET_CONFIG.format( - app=json.dumps(appname), - arg=json.dumps(name), - opts=json.dumps(opts, sort_keys=True), - ) - - run_applescript(script, lang="JavaScript") - - -def search_in_alfred(query=None): - """Open Alfred with given search query. - - Omit ``query`` to simply open Alfred's main window. - - Args: - query (str, optional): Search query. - - """ - query = query or "" - appname = "com.runningwithcrayons.Alfred" - script = JXA_SEARCH.format(app=json.dumps(appname), arg=json.dumps(query)) - run_applescript(script, lang="JavaScript") - - -def browse_in_alfred(path): - """Open Alfred's filesystem navigation mode at ``path``. - - Args: - path (str): File or directory path. - - """ - appname = "com.runningwithcrayons.Alfred" - script = JXA_BROWSE.format(app=json.dumps(appname), arg=json.dumps(path)) - run_applescript(script, lang="JavaScript") - - -def action_in_alfred(paths): - """Action the give filepaths in Alfred. - - Args: - paths (list): Paths to files/directories to action. - - """ - appname = "com.runningwithcrayons.Alfred" - script = JXA_ACTION.format(app=json.dumps(appname), arg=json.dumps(paths)) - run_applescript(script, lang="JavaScript") - - -def reload_workflow(bundleid=None): - """Tell Alfred to reload a workflow from disk. - - If ``bundleid`` is not specified, the bundle ID of the calling - workflow is used. - - Args: - bundleid (str, optional): Bundle ID of workflow to reload. - - """ - bundleid = bundleid or os.getenv("alfred_workflow_bundleid") - appname = "com.runningwithcrayons.Alfred" - script = JXA_RELOAD_WORKFLOW.format( - app=json.dumps(appname), arg=json.dumps(bundleid) - ) - - run_applescript(script, lang="JavaScript") - - -def appinfo(name): - """Get information about an installed application. - - Args: - name (str): Name of application to look up. - - Returns: - AppInfo: :class:`AppInfo` tuple or ``None`` if app isn't found. - - """ - cmd = [ - "mdfind", - "-onlyin", - "/Applications", - "-onlyin", - "/System/Applications", - "-onlyin", - os.path.expanduser("~/Applications"), - "(kMDItemContentTypeTree == com.apple.application &&" - f'(kMDItemDisplayName == "{name}" || kMDItemFSName == "{name}.app"))', - ] - - output = subprocess.run(cmd, check=True, stdout=subprocess.PIPE).stdout.strip() - if not output: - return None - - path = output.split("\n")[0] - - cmd = ["mdls", "-raw", "-name", "kMDItemCFBundleIdentifier", path] - bid = subprocess.run(cmd, check=True, stdout=subprocess.PIPE).stdout.strip() - if not bid: # pragma: no cover - return None - - return AppInfo(name, path, bid) - - -@contextmanager -def atomic_writer(fpath, mode): - """Atomic file writer. - - Context manager that ensures the file is only written if the write - succeeds. The data is first written to a temporary file. - - :param fpath: path of file to write to. - :type fpath: ``str`` - :param mode: sames as for :func:`open` - :type mode: string - - """ - suffix = f".{os.getpid()}.tmp" - temppath = fpath + suffix - with open(temppath, mode) as f: # pylint: disable=unspecified-encoding - try: - yield f - os.rename(temppath, fpath) - finally: - try: - os.remove(temppath) - except (OSError, IOError): - pass - - -class LockFile: - """Context manager to protect filepaths with lockfiles. - - Creates a lockfile alongside ``protected_path``. Other ``LockFile`` - instances will refuse to lock the same path. - - >>> path = '/path/to/file' - >>> with LockFile(path): - >>> with open(path, 'wb') as f: - >>> f.write(data) - - Args: - protected_path (str): File to protect with a lockfile - timeout (float, optional): Raises an :class:`AcquisitionError` - if lock cannot be acquired within this number of seconds. - If ``timeout`` is 0 (the default), wait forever. - delay (float, optional): How often to check (in seconds) if - lock has been released. - - Attributes: - delay (float): How often to check (in seconds) whether the lock - can be acquired. - lockfile (str): Path of the lockfile. - timeout (float): How long to wait to acquire the lock. - - """ - - def __init__(self, protected_path, timeout=0.0, delay=0.05): - """Create new :class:`LockFile` object.""" - self.lockfile = protected_path + ".lock" - self._lockfile = None - self.timeout = timeout - self.delay = delay - self._lock = Event() - atexit.register(self.release) - - @property - def locked(self): - """``True`` if file is locked by this instance.""" - return self._lock.is_set() - - def acquire(self, blocking=True): - """Acquire the lock if possible. - - If the lock is in use and ``blocking`` is ``False``, return - ``False``. - - Otherwise, check every :attr:`delay` seconds until it acquires - lock or exceeds attr:`timeout` and raises an :class:`AcquisitionError`. - - """ - if self.locked and not blocking: - return False - - start = time.time() - while True: - # Raise error if we've been waiting too long to acquire the lock - if self.timeout and (time.time() - start) >= self.timeout: - raise AcquisitionError("lock acquisition timed out") - - # If already locked, wait then try again - if self.locked: - time.sleep(self.delay) - continue - - # Create in append mode so we don't lose any contents - if self._lockfile is None: - with open(self.lockfile, "a", encoding="utf-8") as self._lockfile: - # Try to acquire the lock - try: - fcntl.lockf(self._lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB) - self._lock.set() - break - except IOError as err: # pragma: no cover - if err.errno not in (errno.EACCES, errno.EAGAIN): - raise - - # Don't try again - if not blocking: # pragma: no cover - return False - - # Wait, then try again - time.sleep(self.delay) - - return True - - def release(self): - """Release the lock by deleting `self.lockfile`.""" - if not self._lock.is_set(): - return False - - try: - fcntl.lockf(self._lockfile, fcntl.LOCK_UN) - except IOError: # pragma: no cover - pass - finally: - self._lock.clear() - self._lockfile = None - try: - os.unlink(self.lockfile) - except (IOError, OSError): # pragma: no cover - pass - - return True # pylint: disable=lost-exception - - def __enter__(self): - """Acquire lock.""" - self.acquire() - return self - - def __exit__(self, typ, value, traceback): - """Release lock.""" - self.release() - - def __del__(self): - """Clear up `self.lockfile`.""" - self.release() # pragma: no cover - - -class uninterruptible: # pylint: disable=invalid-name - """Decorator that postpones SIGTERM until wrapped function returns. - - .. important:: This decorator is NOT thread-safe. - - As of version 2.7, Alfred allows Script Filters to be killed. If - your workflow is killed in the middle of critical code (e.g. - writing data to disk), this may corrupt your workflow's data. - - Use this decorator to wrap critical functions that *must* complete. - If the script is killed while a wrapped function is executing, - the SIGTERM will be caught and handled after your function has - finished executing. - - Alfred-Workflow uses this internally to ensure its settings, data - and cache writes complete. - - """ - - def __init__(self, func, class_name=""): - """Decorate `func`.""" - self.func = func - functools.update_wrapper(self, func) - self.class_name = class_name - self._caught_signal = None - self.old_signal_handler = signal.getsignal(signal.SIGTERM) - - def signal_handler(self, signum, frame): - """Called when process receives SIGTERM.""" - self._caught_signal = (signum, frame) - - def __call__(self, *args, **kwargs): - """Trap ``SIGTERM`` and call wrapped function.""" - self._caught_signal = None - # Register handler for SIGTERM, then call `self.func` - signal.signal(signal.SIGTERM, self.signal_handler) - self.func(*args, **kwargs) - - # Restore old signal handler - signal.signal(signal.SIGTERM, self.old_signal_handler) - - # Handle any signal caught during execution - if self._caught_signal is not None: - signum, frame = self._caught_signal - if callable(self.old_signal_handler): - self.old_signal_handler(signum, frame) - elif self.old_signal_handler == signal.SIG_DFL: - sys.exit(0) - - def __get__(self, obj=None, class_name=None): - """Decorator API.""" - return self.__class__(self.func.__get__(obj, class_name), class_name.__name__) diff --git a/src/lib/xp_workflow/version b/src/lib/xp_workflow/version deleted file mode 100644 index 359a5b9..0000000 --- a/src/lib/xp_workflow/version +++ /dev/null @@ -1 +0,0 @@ -2.0.0 \ No newline at end of file diff --git a/src/lib/xp_workflow/web.py b/src/lib/xp_workflow/web.py deleted file mode 100644 index 146f485..0000000 --- a/src/lib/xp_workflow/web.py +++ /dev/null @@ -1,750 +0,0 @@ -"""Lightweight HTTP library with a requests-like interface.""" - -import codecs -import json -import mimetypes -import os -import random -import re -import socket -import string -import unicodedata -import urllib.request -import urllib.parse -import urllib.error -import zlib - -# pylint: disable=consider-using-with -__version__ = open( - os.path.join(os.path.dirname(__file__), "version"), encoding="utf-8" -).read() - -USER_AGENT = f"Alpynist/{__version__}" - -# Valid characters for multipart form data boundaries -BOUNDARY_CHARS = string.digits + string.ascii_letters - -# HTTP response codes -RESPONSES = { - 100: "Continue", - 101: "Switching Protocols", - 200: "OK", - 201: "Created", - 202: "Accepted", - 203: "Non-Authoritative Information", - 204: "No Content", - 205: "Reset Content", - 206: "Partial Content", - 300: "Multiple Choices", - 301: "Moved Permanently", - 302: "Found", - 303: "See Other", - 304: "Not Modified", - 305: "Use Proxy", - 307: "Temporary Redirect", - 400: "Bad Request", - 401: "Unauthorized", - 402: "Payment Required", - 403: "Forbidden", - 404: "Not Found", - 405: "Method Not Allowed", - 406: "Not Acceptable", - 407: "Proxy Authentication Required", - 408: "Request Timeout", - 409: "Conflict", - 410: "Gone", - 411: "Length Required", - 412: "Precondition Failed", - 413: "Request Entity Too Large", - 414: "Request-URI Too Long", - 415: "Unsupported Media Type", - 416: "Requested Range Not Satisfiable", - 417: "Expectation Failed", - 500: "Internal Server Error", - 501: "Not Implemented", - 502: "Bad Gateway", - 503: "Service Unavailable", - 504: "Gateway Timeout", - 505: "HTTP Version Not Supported", -} - - -class NoRedirectHandler(urllib.request.HTTPRedirectHandler): - """Prevent redirections.""" - - def redirect_request(self, *args): # pylint: disable=unused-argument - """Ignore redirect.""" - return None - - -# Adapted from https://gist.github.com/babakness/3901174 -class CaseInsensitiveDictionary(dict): - """Dictionary with caseless key search. - - Enables case insensitive searching while preserving case sensitivity - when keys are listed, ie, via keys() or items() methods. - - Works by storing a lowercase version of the key as the new key and - stores the original key-value pair as the key's value - (values become dictionaries). - - """ - - def __init__(self, initval=None): - """Create new case-insensitive dictionary.""" - super().__init__(self) - - if isinstance(initval, dict): - for key, value in initval.items(): - self.__setitem__(key, value) - elif isinstance(initval, list): - for (key, value) in initval: - self.__setitem__(key, value) - - def __contains__(self, key): - return dict.__contains__(self, key.lower()) - - def __getitem__(self, key): - return dict.__getitem__(self, key.lower())["val"] - - def __setitem__(self, key, value): - return dict.__setitem__(self, key.lower(), {"key": key, "val": value}) - - def get(self, key, default=None): - """Return value for case-insensitive key or default.""" - try: - v = dict.__getitem__(self, key.lower()) - except KeyError: - return default - else: - return v["val"] - - def update(self, other): - """Update values from other ``dict``.""" - for k, v in list(other.items()): - self[k] = v - - def items(self): - """Return ``(key, value)`` pairs.""" - return [(v["key"], v["val"]) for v in dict.values(self)] - - def keys(self): - """Return original keys.""" - return [v["key"] for v in dict.values(self)] - - def values(self): - """Return all values.""" - return [v["val"] for v in dict.values(self)] - - def iteritems(self): - """Iterate over ``(key, value)`` pairs.""" - for v in dict.values(self): - yield v["key"], v["val"] - - def iterkeys(self): - """Iterate over original keys.""" - for v in dict.values(self): - yield v["key"] - - def itervalues(self): - """Interate over values.""" - for v in dict.values(self): - yield v["val"] - - -class Request(urllib.request.Request): - """Subclass of :class:`urllib.request.Request` that supports custom methods.""" - - def __init__(self, *args, **kwargs): - """Create a new :class:`Request`.""" - self._method = kwargs.pop("method", None) - urllib.request.Request.__init__(self, *args, **kwargs) - - def get_method(self): - return self._method.upper() - - -class Response: - """ - Returned by :func:`request` / :func:`get` / :func:`post` functions. - - Simplified version of the ``Response`` object in the ``requests`` library. - - >>> r = request('http://www.google.com') - >>> r.status_code # int - 200 - >>> r.encoding # str - ISO-8859-1 - >>> r.content # bytes - ... - >>> r.text # str, decoded according to charset in HTTP header/meta tag - ... - >>> r.json() # content parsed as JSON - - """ - - def __init__(self, request, stream=False): - """Call `request` with :mod:`urllib` and process results. - - :param request: :class:`Request` instance - :param stream: Whether to stream response or retrieve it all at once - :type stream: bool - - """ - self.request = request - self._stream = stream - self.url = None - self.raw = None - self._encoding = None - self.error = None - self.status_code = None - self.reason = None - self.headers = CaseInsensitiveDictionary() - self._content = None - self._content_loaded = False - self._gzipped = False - - # Execute query - try: - # pylint: disable=consider-using-with - self.raw = urllib.request.urlopen(request) - except urllib.error.HTTPError as err: - self.error = err - try: - self.url = err.geturl() - # sometimes (e.g. when authentication fails) - # urllib can't get a URL from an HTTPError - # This behaviour changes across Python versions, - # so no test cover (it isn't important). - except AttributeError: # pragma: no cover - pass - self.status_code = err.code - else: - self.status_code = self.raw.getcode() - self.url = self.raw.geturl() - self.reason = RESPONSES.get(self.status_code) - - # Parse additional info if request succeeded - if not self.error: - headers = self.raw.info() - self.transfer_encoding = headers.get_content_charset() - self.mimetype = headers.get("content-type") - for key in list(headers.keys()): - self.headers[key.lower()] = headers.get(key) - - # Is content gzipped? - # Transfer-Encoding appears to not be used in the wild - # (contrary to the HTTP standard), but no harm in testing - # for it - if "gzip" in headers.get("content-encoding", "") or "gzip" in headers.get( - "transfer-encoding", "" - ): - self._gzipped = True - - @property - def stream(self): - """Whether response is streamed. - - Returns: - bool: `True` if response is streamed. - - """ - return self._stream - - @stream.setter - def stream(self, value): - if self._content_loaded: - raise RuntimeError("`content` has already been read from this Response.") - - self._stream = value - - def json(self): - """Decode response contents as JSON. - - :returns: object decoded from JSON - :rtype: list, dict or str - - """ - return json.loads(self.content) - - @property - def encoding(self): - """Text encoding of document or ``None``. - - :returns: Text encoding if found. - :rtype: str or ``None`` - - """ - if not self._encoding: - self._encoding = self._get_encoding() - - return self._encoding - - @property - def content(self): - """Raw content of response (i.e. bytes). - - :returns: Body of HTTP response - :rtype: bytes - - """ - if not self._content: - - # Decompress gzipped content - if self._gzipped: - decoder = zlib.decompressobj(16 + zlib.MAX_WBITS) - self._content = decoder.decompress(self.raw.read()) - - else: - self._content = self.raw.read() - - self._content_loaded = True - - return self._content - - @property - def text(self): - """Unicode-decoded content of response body. - - If no encoding can be determined from HTTP headers or the content - itself, the encoded response body will be returned instead. - - :returns: Body of HTTP response - :rtype: str or bytes - - """ - if self.encoding: - return unicodedata.normalize("NFC", str(self.content, self.encoding)) - return self.content - - def iter_content(self, chunk_size=4096, decode_unicode=False): - """Iterate over response data. - - :param chunk_size: Number of bytes to read into memory - :type chunk_size: int - :param decode_unicode: Decode to Unicode using detected encoding - :type decode_unicode: bool - :returns: iterator - - """ - if not self.stream: - raise RuntimeError( - "You cannot call `iter_content` on a Response unless you passed `stream=True` to `get()`/`post()`/`request()`." # noqa - ) - - if self._content_loaded: - raise RuntimeError("`content` has already been read from this Response.") - - def decode_stream(iterator, r): - dec = codecs.getincrementaldecoder(r.encoding)(errors="replace") - - for chunk in iterator: - data = dec.decode(chunk) - if data: - yield data - - data = dec.decode(b"", final=True) - if data: # pragma: no cover - yield data - - def generate(): - if self._gzipped: - decoder = zlib.decompressobj(16 + zlib.MAX_WBITS) - - while True: - chunk = self.raw.read(chunk_size) - if not chunk: - break - - if self._gzipped: - chunk = decoder.decompress(chunk) - - yield chunk - - chunks = generate() - - if decode_unicode and self.encoding: - chunks = decode_stream(chunks, self) - - return chunks - - def save_to_path(self, filepath): - """Save retrieved data to file at ``filepath``. - - :param filepath: Path to save retrieved data. - - """ - filepath = os.path.abspath(filepath) - dirname = os.path.dirname(filepath) - if not os.path.exists(dirname): - os.makedirs(dirname) - - self.stream = True - - with open(filepath, "wb") as fileobj: - for data in self.iter_content(): - fileobj.write(data) - - def raise_for_status(self): - """Raise stored error if one occurred. - - error will be instance of :class:`urllib.error.HTTPError` - """ - if self.error is not None: - raise self.error - - def _get_encoding(self): - """Get encoding from HTTP headers or content. - - :returns: encoding or `None` - :rtype: str or ``None`` - - """ - headers = self.raw.info() - encoding = None - - if headers.get_content_charset(): - encoding = headers.get_content_charset() - - if not self.stream: # Try sniffing response content - # Encoding declared in document should override HTTP headers - if self.mimetype == "text/html": # sniff HTML headers - match = re.search( - r"""""", self.content - ) - if match: - encoding = match.group(1) - - elif ( - self.mimetype.startswith("application/") - or self.mimetype.startswith("text/") - ) and "xml" in self.mimetype: # noqa - match = re.search( - r"""]*\?>""", self.content - ) - if match: - encoding = match.group(1) - - # Format defaults - if self.mimetype == "application/json" and not encoding: - # The default encoding for JSON - encoding = "utf-8" - - elif self.mimetype == "application/xml" and not encoding: - # The default for 'application/xml' - encoding = "utf-8" - - if encoding: - encoding = encoding.lower() - - return encoding - - -def request( - method, - url, - params=None, - data=None, - headers=None, - files=None, - auth=None, - timeout=60, - allow_redirects=False, - stream=False, -): - """Initiate an HTTP(S) request. Returns :class:`Response` object. - - :param method: 'GET' or 'POST' - :type method: str - :param url: URL to open - :type url: str - :param params: mapping of URL parameters - :type params: dict - :param data: mapping of form data ``{'field_name': 'value'}`` or - :class:`str` - :type data: dict or str - :param headers: HTTP headers - :type headers: dict - :param cookies: cookies to send to server - :type cookies: dict - :param files: files to upload (see below). - :type files: dict - :param auth: username, password - :type auth: tuple - :param timeout: connection timeout limit in seconds - :type timeout: int - :param allow_redirects: follow redirections - :type allow_redirects: bool - :param stream: Stream content instead of fetching it all at once. - :type stream: bool - :returns: Response object - :rtype: :class:`Response` - - The ``files`` argument is a dictionary:: - - { - "fieldname": { - "filename": "blah.txt", - "content": "", - "mimetype": "text/plain", - } - } - - * ``fieldname`` is the name of the field in the HTML form. - * ``mimetype`` is optional. If not provided, :mod:`mimetypes` will - be used to guess the mimetype, or ``application/octet-stream`` - will be used. - - """ - # TODO: cookies - socket.setdefaulttimeout(timeout) - - # Default handlers - openers = [urllib.request.ProxyHandler(urllib.request.getproxies())] - - if not allow_redirects: - openers.append(NoRedirectHandler()) - - if auth is not None: # Add authorisation handler - username, password = auth - password_manager = urllib.request.HTTPPasswordMgrWithDefaultRealm() - password_manager.add_password(None, url, username, password) - auth_manager = urllib.request.HTTPBasicAuthHandler(password_manager) - openers.append(auth_manager) - - # Install our custom chain of openers - opener = urllib.request.build_opener(*openers) - urllib.request.install_opener(opener) - - if not headers: - headers = CaseInsensitiveDictionary() - else: - headers = CaseInsensitiveDictionary(headers) - - if "user-agent" not in headers: - headers["user-agent"] = USER_AGENT - - # Accept gzip-encoded content - encodings = [s.strip() for s in headers.get("accept-encoding", "").split(",")] - if "gzip" not in encodings: - encodings.append("gzip") - - headers["accept-encoding"] = ", ".join(encodings) - - if files: - if not data: - data = {} - new_headers, data = encode_multipart_formdata(data, files) - headers.update(new_headers) - elif data and isinstance(data, dict): - data = urllib.parse.urlencode(data) - - # Make sure everything is encoded text - - if params: # GET args (POST args are handled in encode_multipart_formdata) - - scheme, netloc, path, query, fragment = urllib.parse.urlsplit(url) - - if query: # Combine query string and `params` - url_params = urllib.parse.parse_qs(query) - # `params` take precedence over URL query string - url_params.update(params) - params = url_params - - query = urllib.parse.urlencode(params, doseq=True) - url = urllib.parse.urlunsplit((scheme, netloc, path, query, fragment)) - - req = Request(url, data, headers, method=method) - return Response(req, stream) - - -def get( - url, - params=None, - headers=None, - auth=None, - timeout=60, - allow_redirects=True, - stream=False, -): - """Initiate a GET request. Arguments as for :func:`request`. - - :returns: :class:`Response` instance - - """ - return request( - "GET", - url, - params, - headers=headers, - auth=auth, - timeout=timeout, - allow_redirects=allow_redirects, - stream=stream, - ) - - -def delete( - url, - params=None, - data=None, - headers=None, - auth=None, - timeout=60, - allow_redirects=True, - stream=False, -): - """Initiate a DELETE request. Arguments as for :func:`request`. - - :returns: :class:`Response` instance - - """ - return request( - "DELETE", - url, - params, - data, - headers=headers, - auth=auth, - timeout=timeout, - allow_redirects=allow_redirects, - stream=stream, - ) - - -def post( - url, - params=None, - data=None, - headers=None, - files=None, - auth=None, - timeout=60, - allow_redirects=False, - stream=False, -): - """Initiate a POST request. Arguments as for :func:`request`. - - :returns: :class:`Response` instance - - """ - return request( - "POST", - url, - params, - data, - headers, - files, - auth, - timeout, - allow_redirects, - stream, - ) - - -def put( - url, - params=None, - data=None, - headers=None, - files=None, - auth=None, - timeout=60, - allow_redirects=False, - stream=False, -): - """Initiate a PUT request. Arguments as for :func:`request`. - - :returns: :class:`Response` instance - - """ - return request( - "PUT", url, params, data, headers, files, auth, timeout, allow_redirects, stream - ) - - -def encode_multipart_formdata(fields, files): - """Encode form data (``fields``) and ``files`` for POST request. - - :param fields: mapping of ``{name: value}`` pairs for normal form fields. - :type fields: dict - :param files: dictionary of fieldnames/files elements for file data. - See below for details. - :type files: dict of :class:`dict` - :returns: ``(headers, body)`` ``headers`` is a - :class:`dict` of HTTP headers - :rtype: 2-tuple ``(dict, str)`` - - The ``files`` argument is a dictionary:: - - { - "fieldname": { - "filename": "blah.txt", - "content": "", - "mimetype": "text/plain", - } - } - - - ``fieldname`` is the name of the field in the HTML form. - - ``mimetype`` is optional. If not provided, :mod:`mimetypes` will - be used to guess the mimetype, or ``application/octet-stream`` - will be used. - - """ - - def get_content_type(filename): - """Return or guess mimetype of ``filename``. - - :param filename: filename of file - :type filename: unicode/str - :returns: mime-type, e.g. ``text/html`` - :rtype: str - - """ - return mimetypes.guess_type(filename)[0] or "application/octet-stream" - - boundary = "-----" + "".join(random.choice(BOUNDARY_CHARS) for i in range(30)) - crlf = "\r\n" - output = [] - - # Normal form fields - for (k, v) in list(fields.items()): - if isinstance(k, str): - k = k.encode("utf-8") - if isinstance(v, str): - v = v.encode("utf-8") - output.append("--" + boundary) - output.append(f'Content-Disposition: form-data; name="{k}"') - output.append("") - output.append(v) - - # Files to upload - for k, v in list(files.items()): - filename = v["filename"] - content = v["content"] - if "mimetype" in v: - mimetype = v["mimetype"] - else: - mimetype = get_content_type(filename) - if isinstance(k, str): - k = k.encode("utf-8") - if isinstance(filename, str): - filename = filename.encode("utf-8") - if isinstance(mimetype, str): - mimetype = mimetype.encode("utf-8") - output.append("--" + boundary) - output.append( - f'Content-Disposition: form-data; name="{k}"; filename="{filename}"' # noqa - ) - output.append(f"Content-Type: {mimetype}") - output.append("") - output.append(content) - - output.append("--" + boundary + "--") - output.append("") - body = crlf.join(output) - headers = { - "Content-Type": f"multipart/form-data; boundary={boundary}", - "Content-Length": str(len(body)), - } - return (headers, body) diff --git a/src/lib/xp_workflow/workflow.py b/src/lib/xp_workflow/workflow.py deleted file mode 100644 index e57d5c9..0000000 --- a/src/lib/xp_workflow/workflow.py +++ /dev/null @@ -1,3109 +0,0 @@ -# This is a port to Python 3 of the Alfred-Workflow library created by -# Dean Jackson . -# See https://github.com/deanishe/alfred-workflow -# -# Copyright (c) 2022 Arthur Pinheiro - -"""The :class:`Workflow` object is the main interface to this library. - -See :ref:`setup` in the :ref:`user-manual` for an example of how to set -up your Python script to best utilise the :class:`Workflow` object. - -""" - -import binascii -import json -import logging -import logging.handlers -import os -import pickle -import plistlib -import re -import shutil -import string -import subprocess -import sys -import time -import unicodedata -from contextlib import contextmanager -from copy import deepcopy -from typing import Optional -from uuid import uuid4 - -from . import update -from .update import Version -from .util import atomic_writer, LockFile, uninterruptible, set_config - - -#: Sentinel for properties that haven't been set yet (that might -#: correctly have the value ``None``) -UNSET = object() - -#################################################################### -# Standard system icons -#################################################################### - -ICON_ROOT = "/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources" - -ICON_ACCOUNT = os.path.join(ICON_ROOT, "Accounts.icns") -ICON_BURN = os.path.join(ICON_ROOT, "BurningIcon.icns") -ICON_CLOCK = os.path.join(ICON_ROOT, "Clock.icns") -ICON_COLOR = os.path.join(ICON_ROOT, "ProfileBackgroundColor.icns") -ICON_COLOUR = ICON_COLOR # Queen's English, if you please -ICON_EJECT = os.path.join(ICON_ROOT, "EjectMediaIcon.icns") -# Shown when a workflow throws an error -ICON_ERROR = os.path.join(ICON_ROOT, "AlertStopIcon.icns") -ICON_FAVORITE = os.path.join(ICON_ROOT, "ToolbarFavoritesIcon.icns") -ICON_FAVOURITE = ICON_FAVORITE -ICON_GROUP = os.path.join(ICON_ROOT, "GroupIcon.icns") -ICON_HELP = os.path.join(ICON_ROOT, "HelpIcon.icns") -ICON_HOME = os.path.join(ICON_ROOT, "HomeFolderIcon.icns") -ICON_INFO = os.path.join(ICON_ROOT, "ToolbarInfo.icns") -ICON_NETWORK = os.path.join(ICON_ROOT, "GenericNetworkIcon.icns") -ICON_NOTE = os.path.join(ICON_ROOT, "AlertNoteIcon.icns") -ICON_SETTINGS = os.path.join(ICON_ROOT, "ToolbarAdvanced.icns") -ICON_SWIRL = os.path.join(ICON_ROOT, "ErasingIcon.icns") -ICON_SWITCH = os.path.join(ICON_ROOT, "General.icns") -ICON_SYNC = os.path.join(ICON_ROOT, "Sync.icns") -ICON_TRASH = os.path.join(ICON_ROOT, "TrashIcon.icns") -ICON_USER = os.path.join(ICON_ROOT, "UserIcon.icns") -ICON_WEB = os.path.join(ICON_ROOT, "BookmarkIcon.icns") - -#################################################################### -# non-ASCII to ASCII diacritic folding. -# Used by `fold_to_ascii` method -#################################################################### - -ASCII_REPLACEMENTS = { - "À": "A", - "Á": "A", - "Â": "A", - "Ã": "A", - "Ä": "A", - "Å": "A", - "Æ": "AE", - "Ç": "C", - "È": "E", - "É": "E", - "Ê": "E", - "Ë": "E", - "Ì": "I", - "Í": "I", - "Î": "I", - "Ï": "I", - "Ð": "D", - "Ñ": "N", - "Ò": "O", - "Ó": "O", - "Ô": "O", - "Õ": "O", - "Ö": "O", - "Ø": "O", - "Ù": "U", - "Ú": "U", - "Û": "U", - "Ü": "U", - "Ý": "Y", - "Þ": "Th", - "ß": "ss", - "à": "a", - "á": "a", - "â": "a", - "ã": "a", - "ä": "a", - "å": "a", - "æ": "ae", - "ç": "c", - "è": "e", - "é": "e", - "ê": "e", - "ë": "e", - "ì": "i", - "í": "i", - "î": "i", - "ï": "i", - "ð": "d", - "ñ": "n", - "ò": "o", - "ó": "o", - "ô": "o", - "õ": "o", - "ö": "o", - "ø": "o", - "ù": "u", - "ú": "u", - "û": "u", - "ü": "u", - "ý": "y", - "þ": "th", - "ÿ": "y", - "Ł": "L", - "ł": "l", - "Ń": "N", - "ń": "n", - "Ņ": "N", - "ņ": "n", - "Ň": "N", - "ň": "n", - "Ŋ": "ng", - "ŋ": "NG", - "Ō": "O", - "ō": "o", - "Ŏ": "O", - "ŏ": "o", - "Ő": "O", - "ő": "o", - "Œ": "OE", - "œ": "oe", - "Ŕ": "R", - "ŕ": "r", - "Ŗ": "R", - "ŗ": "r", - "Ř": "R", - "ř": "r", - "Ś": "S", - "ś": "s", - "Ŝ": "S", - "ŝ": "s", - "Ş": "S", - "ş": "s", - "Š": "S", - "š": "s", - "Ţ": "T", - "ţ": "t", - "Ť": "T", - "ť": "t", - "Ŧ": "T", - "ŧ": "t", - "Ũ": "U", - "ũ": "u", - "Ū": "U", - "ū": "u", - "Ŭ": "U", - "ŭ": "u", - "Ů": "U", - "ů": "u", - "Ű": "U", - "ű": "u", - "Ŵ": "W", - "ŵ": "w", - "Ŷ": "Y", - "ŷ": "y", - "Ÿ": "Y", - "Ź": "Z", - "ź": "z", - "Ż": "Z", - "ż": "z", - "Ž": "Z", - "ž": "z", - "ſ": "s", - "Α": "A", - "Β": "B", - "Γ": "G", - "Δ": "D", - "Ε": "E", - "Ζ": "Z", - "Η": "E", - "Θ": "Th", - "Ι": "I", - "Κ": "K", - "Λ": "L", - "Μ": "M", - "Ν": "N", - "Ξ": "Ks", - "Ο": "O", - "Π": "P", - "Ρ": "R", - "Σ": "S", - "Τ": "T", - "Υ": "U", - "Φ": "Ph", - "Χ": "Kh", - "Ψ": "Ps", - "Ω": "O", - "α": "a", - "β": "b", - "γ": "g", - "δ": "d", - "ε": "e", - "ζ": "z", - "η": "e", - "θ": "th", - "ι": "i", - "κ": "k", - "λ": "l", - "μ": "m", - "ν": "n", - "ξ": "x", - "ο": "o", - "π": "p", - "ρ": "r", - "ς": "s", - "σ": "s", - "τ": "t", - "υ": "u", - "φ": "ph", - "χ": "kh", - "ψ": "ps", - "ω": "o", - "А": "A", - "Б": "B", - "В": "V", - "Г": "G", - "Д": "D", - "Е": "E", - "Ж": "Zh", - "З": "Z", - "И": "I", - "Й": "I", - "К": "K", - "Л": "L", - "М": "M", - "Н": "N", - "О": "O", - "П": "P", - "Р": "R", - "С": "S", - "Т": "T", - "У": "U", - "Ф": "F", - "Х": "Kh", - "Ц": "Ts", - "Ч": "Ch", - "Ш": "Sh", - "Щ": "Shch", - "Ъ": "'", - "Ы": "Y", - "Ь": "'", - "Э": "E", - "Ю": "Iu", - "Я": "Ia", - "а": "a", - "б": "b", - "в": "v", - "г": "g", - "д": "d", - "е": "e", - "ж": "zh", - "з": "z", - "и": "i", - "й": "i", - "к": "k", - "л": "l", - "м": "m", - "н": "n", - "о": "o", - "п": "p", - "р": "r", - "с": "s", - "т": "t", - "у": "u", - "ф": "f", - "х": "kh", - "ц": "ts", - "ч": "ch", - "ш": "sh", - "щ": "shch", - "ъ": "'", - "ы": "y", - "ь": "'", - "э": "e", - "ю": "iu", - "я": "ia", - "ᴦ": "G", - "ᴧ": "L", - "ᴨ": "P", - "ᴩ": "R", - "ᴪ": "PS", - "ẞ": "Ss", - "Ỳ": "Y", - "ỳ": "y", - "Ỵ": "Y", - "ỵ": "y", - "Ỹ": "Y", - "ỹ": "y", -} - -#################################################################### -# Smart-to-dumb punctuation mapping -#################################################################### - -DUMB_PUNCTUATION = { - "‘": "'", - "’": "'", - "‚": "'", - "“": '"', - "”": '"', - "„": '"', - "–": "-", - "—": "-", -} - -#################################################################### -# Used by `Workflow.filter` -#################################################################### - -# Anchor characters in a name -#: Characters that indicate the beginning of a "word" in CamelCase -INITIALS = string.ascii_uppercase + string.digits - -#: Split on non-letters, numbers -split_on_delimiters = re.compile("[^a-zA-Z0-9]").split - -# Match filter flags -#: Match items that start with ``query`` -MATCH_STARTSWITH = 1 -#: Match items whose capital letters start with ``query`` -MATCH_CAPITALS = 2 -#: Match items with a component "word" that matches ``query`` -MATCH_ATOM = 4 -#: Match items whose initials (based on atoms) start with ``query`` -MATCH_INITIALS_STARTSWITH = 8 -#: Match items whose initials (based on atoms) contain ``query`` -MATCH_INITIALS_CONTAIN = 16 -#: Combination of :const:`MATCH_INITIALS_STARTSWITH` and -#: :const:`MATCH_INITIALS_CONTAIN` -MATCH_INITIALS = 24 -#: Match items if ``query`` is a substring -MATCH_SUBSTRING = 32 -#: Match items if all characters in ``query`` appear in the item in order -MATCH_ALLCHARS = 64 -#: Combination of all other ``MATCH_*`` constants -MATCH_ALL = 127 - -#################################################################### -# Used by `Workflow.check_update` -#################################################################### - -# Number of days to wait between checking for updates to the workflow -DEFAULT_UPDATE_FREQUENCY = 1 - -#################################################################### -# Keychain access errors -#################################################################### - - -class KeychainError(Exception): - """Raised for unknown Keychain errors. - - Raised by methods :meth:`Workflow.save_password`, - :meth:`Workflow.get_password` and :meth:`Workflow.delete_password` - when ``security`` CLI app returns an unknown error code. - - """ - - -class PasswordNotFound(KeychainError): - """Password not in Keychain. - - Raised by method :meth:`Workflow.get_password` when ``account`` - is unknown to the Keychain. - - """ - - -class PasswordExists(KeychainError): - """Raised when trying to overwrite an existing account password. - - You should never receive this error: it is used internally - by the :meth:`Workflow.save_password` method to know if it needs - to delete the old password first (a Keychain implementation detail). - - """ - - -#################################################################### -# Helper functions -#################################################################### - - -def isascii(text): - """Test if ``text`` contains only ASCII characters. - :param text: text to test for ASCII-ness - :type text: ``str`` - :returns: ``True`` if ``text`` contains only ASCII characters - :rtype: ``Boolean`` - """ - try: - text.encode("ascii") - except UnicodeEncodeError: - return False - return True - - -#################################################################### -# Implementation classes -#################################################################### - - -class SerializerManager: - """Contains registered serializers. - - A configured instance of this class is available at - :attr:`workflow.manager`. - - Use :meth:`register()` to register new (or replace - existing) serializers, which you can specify by name when calling - :class:`~workflow.Workflow` data storage methods. - - See :ref:`guide-serialization` and :ref:`guide-persistent-data` - for further information. - - """ - - def __init__(self): - """Create new SerializerManager object.""" - self._serializers = {} - - def register(self, name, serializer): - """Register ``serializer`` object under ``name``. - - Raises :class:`AttributeError` if ``serializer`` in invalid. - - .. note:: - - ``name`` will be used as the file extension of the saved files. - - :param name: Name to register ``serializer`` under - :type name: ``str`` - :param serializer: object with ``load()`` and ``dump()`` - methods - - """ - # Basic validation - serializer.load # pylint: disable=pointless-statement - serializer.dump # pylint: disable=pointless-statement - - self._serializers[name] = serializer - - def serializer(self, name): - """Return serializer object for ``name``. - - :param name: Name of serializer to return - :type name: ``str`` - :returns: serializer object or ``None`` if no such serializer - is registered. - - """ - return self._serializers.get(name) - - def unregister(self, name): - """Remove registered serializer with ``name``. - - Raises a :class:`ValueError` if there is no such registered - serializer. - - :param name: Name of serializer to remove - :type name: ``str`` - :returns: serializer object - - """ - if name not in self._serializers: - raise ValueError(f"No such serializer registered : {name}") - - serializer = self._serializers[name] - del self._serializers[name] - - return serializer - - @property - def serializers(self): - """Return names of registered serializers.""" - return sorted(self._serializers.keys()) - - -class BaseSerializer: - """Base class for serializers.""" - - is_binary: Optional[bool] = None - - @classmethod - def binary_mode(cls): - return "b" if cls.is_binary else "" - - @classmethod - def _opener(cls, opener, path, mode="r"): - with opener(path, mode + cls.binary_mode()) as f: - yield f - - @classmethod - @contextmanager - def atomic_writer(cls, path, mode): - yield from cls._opener(atomic_writer, path, mode) - - @classmethod - @contextmanager - def open(cls, path, mode): - yield from cls._opener(open, path, mode) - - -class JSONSerializer(BaseSerializer): - """Wrapper around :mod:`json`. Sets ``indent`` and ``encoding``. - - Use this serializer if you need readable data files. JSON doesn't - support Python objects as well as ``pickle``, so be - careful which data you try to serialize as JSON. - - """ - - is_binary = False - - @classmethod - def load(cls, file_obj): - """Load serialized object from open JSON file. - - :param file_obj: file handle - :type file_obj: ``file`` object - :returns: object loaded from JSON file - :rtype: object - - """ - return json.load(file_obj) - - @classmethod - def dump(cls, obj, file_obj): - """Serialize object ``obj`` to open JSON file. - - :param obj: Python object to serialize - :type obj: JSON-serializable data structure - :param file_obj: file handle - :type file_obj: ``file`` object - - """ - return json.dump(obj, file_obj, indent=2, encoding="utf-8") - - -class PickleSerializer(BaseSerializer): - """Wrapper around :mod:`pickle`. Sets ``protocol``. - - Use this serializer if you need to add custom pickling. - - """ - - is_binary = True - - @classmethod - def load(cls, file_obj): - """Load serialized object from open pickle file. - - :param file_obj: file handle - :type file_obj: ``file`` object - :returns: object loaded from pickle file - :rtype: object - - """ - return pickle.load(file_obj) - - @classmethod - def dump(cls, obj, file_obj): - """Serialize object ``obj`` to open pickle file. - - :param obj: Python object to serialize - :type obj: Python object - :param file_obj: file handle - :type file_obj: ``file`` object - - """ - return pickle.dump(obj, file_obj, protocol=-1) - - -# Set up default manager and register built-in serializers -manager = SerializerManager() -manager.register("pickle", PickleSerializer) -manager.register("json", JSONSerializer) - - -class Item: - """Represents a feedback item for Alfred. - - Generates Alfred-compliant JSON for a single item. - - Don't use this class directly but via :meth:`Workflow.add_item`. - See :meth:`~Workflow.add_item` for details of arguments. - - """ - - def __init__( - self, - title, - subtitle="", - arg=None, - autocomplete=None, - match=None, - valid=False, - uid=None, - icon=None, - icontype=None, - type=None, # pylint: disable=redefined-builtin - largetext=None, - copytext=None, - quicklookurl=None, - ): - """Create a new :class:`Item` object. - - Use same arguments as for - :class:`Workflow.Item `. - - Argument ``subtitle_modifiers`` is not supported. - - """ - self.title = title - self.subtitle = subtitle - self.arg = arg - self.autocomplete = autocomplete - self.match = match - self.valid = valid - self.uid = uid - self.icon = icon - self.icontype = icontype - self.type = type - self.quicklookurl = quicklookurl - self.largetext = largetext - self.copytext = copytext - - self.modifiers = {} - - self.config = {} - self.variables = {} - - def setvar(self, name, value): - """Set a workflow variable for this Item. - - Args: - name (str): Name of variable. - value (str): Value of variable. - - """ - self.variables[name] = value - - def getvar(self, name, default=None): - """Return value of workflow variable for ``name`` or ``default``. - - Args: - name (str): Variable name. - default (None, optional): Value to return if variable is unset. - - Returns: - str or ``default``: Value of variable if set or ``default``. - - """ - return self.variables.get(name, default) - - def add_modifier( - self, key, subtitle=None, arg=None, valid=None, icon=None, icontype=None - ): - """Add alternative values for a modifier key. - - Args: - key (str): Modifier key, e.g. ``"cmd"`` or ``"alt"`` - subtitle (str, optional): Override item subtitle. - arg (str, optional): Input for following action. - valid (bool, optional): Override item validity. - icon (str, optional): Filepath/UTI of icon. - icontype (str, optional): Type of icon. See - :meth:`Workflow.add_item() ` - for valid values. - - In Alfred 4.1+, ``arg`` may also be a :class:`list` or :class:`tuple`. - - Returns: - Modifier: Configured :class:`Modifier`. - - """ - mod = Modifier(key, subtitle, arg, valid, icon, icontype) - - # Add Item variables to Modifier - mod.variables.update(self.variables) - - self.modifiers[key] = mod - - return mod - - @property - def obj(self): - """Item formatted for JSON serialization. - - Returns: - dict: Data suitable for Alfred feedback. - - """ - # Required values - obj_ = { - "title": self.title, - "subtitle": self.subtitle, - "valid": self.valid, - } - - # Optional values - if self.arg is not None: - obj_["arg"] = self.arg - - if self.autocomplete is not None: - obj_["autocomplete"] = self.autocomplete - - if self.match is not None: - obj_["match"] = self.match - - if self.uid is not None: - obj_["uid"] = self.uid - - if self.type is not None: - obj_["type"] = self.type - - if self.quicklookurl is not None: - obj_["quicklookurl"] = self.quicklookurl - - if self.variables: - obj_["variables"] = self.variables - - if self.config: - obj_["config"] = self.config - - # Largetype and copytext - text = self._text() - if text: - obj_["text"] = text - - icon = self._icon() - if icon: - obj_["icon"] = icon - - # Modifiers - mods = self._modifiers() - if mods: - obj_["mods"] = mods - - return obj_ - - def _icon(self): - """Return `icon` object for item. - - Returns: - dict: Mapping for item `icon` (may be empty). - - """ - icon = {} - if self.icon is not None: - icon["path"] = self.icon - - if self.icontype is not None: - icon["type"] = self.icontype - - return icon - - def _text(self): - """Return `largetext` and `copytext` object for item. - - Returns: - dict: `text` mapping (may be empty) - - """ - text = {} - if self.largetext is not None: - text["largetype"] = self.largetext - - if self.copytext is not None: - text["copy"] = self.copytext - - return text - - def _modifiers(self): - """Build `mods` dictionary for JSON feedback. - - Returns: - dict: Modifier mapping or `None`. - - """ - if self.modifiers: - mods = {} - for k, mod in self.modifiers.items(): - mods[k] = mod.obj - - return mods - - return None - - -class Variables(dict): - """Workflow variables for Run Script actions. - - This class allows you to set workflow variables from - Run Script actions. - - It is a subclass of :class:`dict`. - - >>> v = Variables(username='deanishe', password='hunter2') - >>> v.arg = u'output value' - >>> print(v) - - See :ref:`variables-run-script` in the User Guide for more - information. - - Args: - arg (str or list, optional): Main output/``{query}``. - **variables: Workflow variables to set. - - In Alfred 4.1+ ``arg`` may also be a :class:`list` or :class:`tuple`. - - Attributes: - arg (str or list): Output value (``{query}``). - In Alfred 4.1+ ``arg`` may also be a :class:`list` or - :class:`tuple`. - config (dict): Configuration for downstream workflow element. - - """ - - def __init__(self, arg=None, **variables): - """Create a new `Variables` object.""" - self.arg = arg - self.config = {} - super().__init__(**variables) - - @property - def obj(self): - """``alfredworkflow`` :class:`dict`.""" - obj_ = {} - if self: - d2 = {} - for k, v in self.items(): - d2[k] = v - obj_["variables"] = d2 - - if self.config: - obj_["config"] = self.config - - if self.arg is not None: - obj_["arg"] = self.arg - - return {"alfredworkflow": obj_} - - -class Modifier: - """Modify :class:`Item` arg/icon/variables when modifier key is pressed. - - Don't use this class directly (as it won't be associated with any - :class:`Item`), but rather use :meth:`Item.add_modifier()` - to add modifiers to results. - - >>> it = wf.add_item('Title', 'Subtitle', valid=True) - >>> it.setvar('name', 'default') - >>> m = it.add_modifier('cmd') - >>> m.setvar('name', 'alternate') - - See :ref:`workflow-variables` in the User Guide for more information - and :ref:`example usage `. - - Args: - key (str): Modifier key, e.g. ``"cmd"``, ``"alt"`` etc. - subtitle (str, optional): Override default subtitle. - arg (str, optional): Argument to pass for this modifier. - valid (bool, optional): Override item's validity. - icon (str, optional): Filepath/UTI of icon to use - icontype (str, optional): Type of icon. See - :meth:`Workflow.add_item() ` - for valid values. - - Attributes: - arg (str): Arg to pass to following action. - config (dict): Configuration for a downstream element, such as - a File Filter. - icon (str): Filepath/UTI of icon. - icontype (str): Type of icon. See - :meth:`Workflow.add_item() ` - for valid values. - key (str): Modifier key (see above). - subtitle (str): Override item subtitle. - valid (bool): Override item validity. - variables (dict): Workflow variables set by this modifier. - - """ - - def __init__( - self, key, subtitle=None, arg=None, valid=None, icon=None, icontype=None - ): - """Create a new :class:`Modifier`. - - Don't use this class directly (as it won't be associated with any - :class:`Item`), but rather use :meth:`Item.add_modifier()` - to add modifiers to results. - - Args: - key (str): Modifier key, e.g. ``"cmd"``, ``"alt"`` etc. - subtitle (str, optional): Override default subtitle. - arg (str, optional): Argument to pass for this modifier. - valid (bool, optional): Override item's validity. - icon (str, optional): Filepath/UTI of icon to use - icontype (str, optional): Type of icon. See - :meth:`Workflow.add_item() ` - for valid values. - - """ - self.key = key - self.subtitle = subtitle - self.arg = arg - self.valid = valid - self.icon = icon - self.icontype = icontype - - self.config = {} - self.variables = {} - - def setvar(self, name, value): - """Set a workflow variable for this Item. - - Args: - name (str): Name of variable. - value (str): Value of variable. - - """ - self.variables[name] = value - - def getvar(self, name, default=None): - """Return value of workflow variable for ``name`` or ``default``. - - Args: - name (str): Variable name. - default (None, optional): Value to return if variable is unset. - - Returns: - str or ``default``: Value of variable if set or ``default``. - - """ - return self.variables.get(name, default) - - @property - def obj(self): - """Modifier formatted for JSON serialization for Alfred 3. - - Returns: - dict: Modifier for serializing to JSON. - - """ - obj_ = {} - - if self.subtitle is not None: - obj_["subtitle"] = self.subtitle - - if self.arg is not None: - obj_["arg"] = self.arg - - if self.valid is not None: - obj_["valid"] = self.valid - - if self.variables: - obj_["variables"] = self.variables - - if self.config: - obj_["config"] = self.config - - icon = self._icon() - if icon: - obj_["icon"] = icon - - return obj_ - - def _icon(self): - """Return `icon` object for item. - - Returns: - dict: Mapping for item `icon` (may be empty). - - """ - icon = {} - if self.icon is not None: - icon["path"] = self.icon - - if self.icontype is not None: - icon["type"] = self.icontype - - return icon - - -class Settings(dict): - """A dictionary that saves itself when changed. - - Dictionary keys & values will be saved as a JSON file - at ``filepath``. If the file does not exist, the dictionary - (and settings file) will be initialised with ``defaults``. - - :param filepath: where to save the settings - :type filepath: :class:`str` - :param defaults: dict of default settings - :type defaults: :class:`dict` - - - An appropriate instance is provided by :class:`Workflow` instances at - :attr:`Workflow.settings`. - - """ - - def __init__(self, filepath, defaults=None): - """Create new :class:`Settings` object.""" - super().__init__() - self._filepath = filepath - self._nosave = False - self._original = {} - if os.path.exists(self._filepath): - self._load() - elif defaults: - for key, val in defaults.items(): - self[key] = val - self.save() # save default settings - - def _load(self): - """Load cached settings from JSON file `self._filepath`.""" - data = {} - with LockFile(self._filepath, 0.5): - with open(self._filepath, "rb") as f: - data.update(json.load(f)) - - self._original = deepcopy(data) - - self._nosave = True - self.update(data) - self._nosave = False - - @uninterruptible - def save(self): - """Save settings to JSON file specified in ``self._filepath``. - - If you're using this class via :attr:`Workflow.settings`, which - you probably are, ``self._filepath`` will be ``settings.json`` - in your workflow's data directory (see :attr:`~Workflow.datadir`). - """ - if self._nosave: - return - - data = {} - data.update(self) - - with LockFile(self._filepath, 0.5): - with atomic_writer(self._filepath, "w") as f: - json.dump(data, f, sort_keys=True, indent=2) - - # dict methods - def __setitem__(self, key, value): - """Implement :class:`dict` interface.""" - if self._original.get(key) != value: - super().__setitem__(key, value) - self.save() - - def __delitem__(self, key): - """Implement :class:`dict` interface.""" - super().__delitem__(key) - self.save() - - def update(self, *args, **kwargs): - """Override :class:`dict` method to save on update.""" - super().update(*args, **kwargs) - self.save() - - def setdefault(self, key, value=None): - """Override :class:`dict` method to save on update.""" - ret = super().setdefault(key, value) - self.save() - return ret - - -class Workflow: - """The ``Workflow`` object is the main interface to Alfred-Workflow. - It provides APIs for accessing the Alfred/workflow environment, - storing & caching data, using Keychain, and generating Script - Filter feedback. - ``Workflow`` is compatible with Alfred 3+. - :param default_settings: default workflow settings. If no settings file - exists, :class:`Workflow.settings` will be pre-populated with - ``default_settings``. - :type default_settings: :class:`dict` - :param update_settings: settings for updating your workflow from - GitHub releases. The only required key is ``github_slug``, - whose value must take the form of ``username/repo``. - If specified, ``Workflow`` will check the repo's releases - for updates. Your workflow must also have a semantic version - number. Please see the :ref:`User Manual ` and - `update API docs ` for more information. - :type update_settings: :class:`dict` - :param input_encoding: encoding of command line arguments. You - should probably leave this as the default (``utf-8``), which - is the encoding Alfred uses. - :type input_encoding: :class:`str` - :param normalization: normalization to apply to CLI args. - See :meth:`Workflow.decode` for more details. - :type normalization: :class:`str` - :param capture_args: Capture and act on ``workflow:*`` arguments. See - :ref:`Magic arguments ` for details. - :type capture_args: :class:`Boolean` - :param libraries: sequence of paths to directories containing - libraries. These paths will be prepended to ``sys.path``. - :type libraries: :class:`tuple` or :class:`list` - :param help_url: URL to webpage where a user can ask for help with - the workflow, report bugs, etc. This could be the GitHub repo - or a page on AlfredForum.com. If your workflow throws an error, - this URL will be displayed in the log and Alfred's debugger. It can - also be opened directly in a web browser with the ``workflow:help`` - :ref:`magic argument `. - :type help_url: :class:`str` - """ - - item_class = Item - - def __init__( - self, - default_settings=None, - update_settings=None, - input_encoding="utf-8", - normalization="NFC", - capture_args=True, - libraries=None, - help_url=None, - ): - """Create new :class:`Workflow` object.""" - self._default_settings = default_settings or {} - self._update_settings = update_settings or {} - self._input_encoding = input_encoding - self._normalization = normalization - self._capture_args = capture_args - self.help_url = help_url - self._workflowdir = None - self._settings_path = None - self._settings = None - self._bundleid = None - self._debugging = None - self._name = None - self._cache_serializer = "pickle" - self._data_serializer = "pickle" - self._info = None - self._info_loaded = False - self._logger = None - self._items = [] - self._alfred_env = None - # Version number of the workflow - self._version = UNSET - # Version from last workflow run - self._last_version_run = UNSET - # Cache for regex patterns created for filter keys - self._search_pattern_cache = {} - #: Prefix for all magic arguments. - #: The default value is ``workflow:`` so keyword - #: ``config`` would match user query ``workflow:config``. - self.magic_prefix = "workflow:" - #: Mapping of available magic arguments. The built-in magic - #: arguments are registered by default. To add your own magic arguments - #: (or override built-ins), add a key:value pair where the key is - #: what the user should enter (prefixed with :attr:`magic_prefix`) - #: and the value is a callable that will be called when the argument - #: is entered. If you would like to display a message in Alfred, the - #: function should return a ``str`` - #: - #: By default, the magic arguments documented - #: :ref:`here ` are registered. - self.magic_arguments = {} - self._register_default_magic() - self.variables = {} - self._rerun = 0 - # Get session ID from environment if present - self._session_id = os.getenv("_WF_SESSION_ID") or None - if self._session_id: - self.setvar("_WF_SESSION_ID", self._session_id) - if libraries: - sys.path = libraries + sys.path - - #################################################################### - # API methods - #################################################################### - - # info.plist contents and alfred_* environment variables ---------- - - @property - def alfred_version(self): - """Alfred version as :class:`~workflow.update.Version` object.""" - return Version(self.alfred_env.get("version")) - - @property - def alfred_env(self): - """Dict of Alfred's environmental variables minus ``alfred_`` prefix. - - The variables Alfred exports are: - - ============================ ========================================= - Variable Description - ============================ ========================================= - debug Set to ``1`` if Alfred's debugger is - open, otherwise unset. - preferences Path to Alfred.alfredpreferences - (where your workflows and settings are - stored). - preferences_localhash Machine-specific preferences are stored - in ``Alfred.alfredpreferences/preferences/local/`` - (see ``preferences`` above for - the path to ``Alfred.alfredpreferences``) - theme ID of selected theme - theme_background Background colour of selected theme in - format ``rgba(r,g,b,a)`` - theme_subtext Show result subtext. - ``0`` = Always, - ``1`` = Alternative actions only, - ``2`` = Selected result only, - ``3`` = Never - version Alfred version number, e.g. ``'2.4'`` - version_build Alfred build number, e.g. ``277`` - workflow_bundleid Bundle ID, e.g. - ``net.deanishe.alfred-mailto`` - workflow_cache Path to workflow's cache directory - workflow_data Path to workflow's data directory - workflow_name Name of current workflow - workflow_uid UID of workflow - workflow_version The version number specified in the - workflow configuration sheet/info.plist - ============================ ========================================= - - **Note:** all values are strings except ``version_build`` and - ``theme_subtext``, which are integers. - - :returns: ``dict`` of Alfred's environmental variables without the - ``alfred_`` prefix, e.g. ``preferences``, ``workflow_data``. - - """ - if self._alfred_env is not None: - return self._alfred_env - - data = {} - - for key in ( - "debug", - "preferences", - "preferences_localhash", - "theme", - "theme_background", - "theme_subtext", - "version", - "version_build", - "workflow_bundleid", - "workflow_cache", - "workflow_data", - "workflow_name", - "workflow_uid", - "workflow_version", - ): - - value = os.getenv("alfred_" + key, "") - - if value: - if key in ("debug", "version_build", "theme_subtext"): - value = int(value) - # else: - # value = self.decode(value) - - data[key] = value - - self._alfred_env = data - - return self._alfred_env - - @property - def info(self): - """:class:`dict` of ``info.plist`` contents.""" - if not self._info_loaded: - self._load_info_plist() - return self._info - - @property - def bundleid(self): - """Workflow bundle ID from environmental vars or ``info.plist``. - - :returns: bundle ID - :rtype: ``str`` - - """ - if not self._bundleid: - if self.alfred_env.get("workflow_bundleid"): - self._bundleid = self.alfred_env.get("workflow_bundleid") - else: - self._bundleid = self.info["bundleid"] - - return self._bundleid - - @property - def debugging(self): - """Whether Alfred's debugger is open. - - :returns: ``True`` if Alfred's debugger is open. - :rtype: ``bool`` - - """ - return self.alfred_env.get("debug") == 1 - - @property - def name(self): - """Workflow name from Alfred's environmental vars or ``info.plist``. - - :returns: workflow name - :rtype: ``str`` - - """ - if not self._name: - if self.alfred_env.get("workflow_name"): - self._name = self.decode(self.alfred_env.get("workflow_name")) - else: - self._name = self.decode(self.info["name"]) - - return self._name - - @property - def version(self): - """Return the version of the workflow. - - Get the workflow version from environment variable, - the ``update_settings`` dict passed on - instantiation, the ``version`` file located in the workflow's - root directory or ``info.plist``. Return ``None`` if none - exists or :class:`ValueError` if the version number is invalid - (i.e. not semantic). - - :returns: Version of the workflow (not Alfred-Workflow) - :rtype: :class:`~workflow.update.Version` object - - """ - if self._version is UNSET: - - version = None - # environment variable has priority - if self.alfred_env.get("workflow_version"): - version = self.alfred_env["workflow_version"] - - # Try `update_settings` - elif self._update_settings: - version = self._update_settings.get("version") - - # `version` file - if not version: - filepath = self.workflowfile("version") - - if os.path.exists(filepath): - with open(filepath, "rb") as fileobj: - version = fileobj.read() - - # info.plist - if not version: - version = self.info.get("version") - - if version: - version = Version(version) - - self._version = version - - return self._version - - # Workflow utility methods ----------------------------------------- - - @property - def args(self): - """Return command line args as normalised unicode. - - Args are decoded and normalised via :meth:`~Workflow.decode`. - - The encoding and normalization are the ``input_encoding`` and - ``normalization`` arguments passed to :class:`Workflow` (``UTF-8`` - and ``NFC`` are the defaults). - - If :class:`Workflow` is called with ``capture_args=True`` - (the default), :class:`Workflow` will look for certain - ``workflow:*`` args and, if found, perform the corresponding - actions and exit the workflow. - - See :ref:`Magic arguments ` for details. - - """ - msg = None - args = [self.decode(arg) for arg in sys.argv[1:]] - - # Handle magic args - if len(args) and self._capture_args: - for k, v in self.magic_arguments.items(): - key = f"{self.magic_prefix}{k}" - if key in args: - msg = v() - - if msg: - self.logger.debug(msg) - if not sys.stdout.isatty(): # Show message in Alfred - self.add_item(msg, valid=False, icon=ICON_INFO) - self.send_feedback() - sys.exit(0) - return args - - @property - def cachedir(self): - """Path to workflow's cache directory. - - The cache directory is a subdirectory of Alfred's own cache directory - in ``~/Library/Caches``. The full path is: - - ``~/Library/Caches/com.runningwithcrayons.Alfred/Workflow Data/`` - - Returns: - str: full path to workflow's cache directory - - """ - if self.alfred_env.get("workflow_cache"): - dirpath = self.alfred_env.get("workflow_cache") - - else: - dirpath = self._default_cachedir - - return self._create(dirpath) - - @property - def _default_cachedir(self): - """Alfred's default cache directory.""" - return os.path.join( - os.path.expanduser( - "~/Library/Caches/com.runningwithcrayons.Alfred/Workflow Data/" - ), - self.bundleid, - ) - - @property - def datadir(self): - """Path to workflow's data directory. - - The data directory is a subdirectory of Alfred's own data directory in - ``~/Library/Application Support``. The full path is: - - ``~/Library/Application Support/Alfred/Workflow Data/`` - - Returns: - str: full path to workflow data directory - - """ - if self.alfred_env.get("workflow_data"): - dirpath = self.alfred_env.get("workflow_data") - - else: - dirpath = self._default_datadir - - return self._create(dirpath) - - @property - def _default_datadir(self): - """Alfred's default data directory.""" - return os.path.join( - os.path.expanduser("~/Library/Application Support/Alfred/Workflow Data/"), - self.bundleid, - ) - - @property - def workflowdir(self): - """Path to workflow's root directory (where ``info.plist`` is). - - Returns: - str: full path to workflow root directory - - """ - if not self._workflowdir: - # Try the working directory first, then the directory - # the library is in. CWD will be the workflow root if - # a workflow is being run in Alfred - candidates = [ - os.path.abspath(os.getcwd()), - os.path.dirname(os.path.abspath(os.path.dirname(__file__))), - ] - - # climb the directory tree until we find `info.plist` - for dirpath in candidates: - while True: - if os.path.exists(os.path.join(dirpath, "info.plist")): - self._workflowdir = dirpath - break - - if dirpath == "/": - # no `info.plist` found - break - - # Check the parent directory - dirpath = os.path.dirname(dirpath) - - # No need to check other candidates - if self._workflowdir: - break - - if not self._workflowdir: - raise IOError("'info.plist' not found in directory tree") - - return self._workflowdir - - def cachefile(self, filename): - """Path to ``filename`` in workflow's cache directory. - - Return absolute path to ``filename`` within your workflow's - :attr:`cache directory `. - - :param filename: basename of file - :type filename: ``str`` - :returns: full path to file within cache directory - :rtype: ``str`` - - """ - return os.path.join(self.cachedir, filename) - - def datafile(self, filename): - """Path to ``filename`` in workflow's data directory. - - Return absolute path to ``filename`` within your workflow's - :attr:`data directory `. - - :param filename: basename of file - :type filename: ``str`` - :returns: full path to file within data directory - :rtype: ``str`` - - """ - return os.path.join(self.datadir, filename) - - def workflowfile(self, filename): - """Return full path to ``filename`` in workflow's root directory. - - :param filename: basename of file - :type filename: ``str`` - :returns: full path to file within data directory - :rtype: ``str`` - - """ - return os.path.join(self.workflowdir, filename) - - @property - def logfile(self): - """Path to logfile. - - :returns: path to logfile within workflow's cache directory - :rtype: ``str`` - - """ - return self.cachefile(f"{self.bundleid}.log") - - @property - def logger(self): - """Logger that logs to both console and a log file. - - If Alfred's debugger is open, log level will be ``DEBUG``, - else it will be ``INFO``. - - Use :meth:`open_log` to open the log file in Console. - - :returns: an initialised :class:`~logging.Logger` - - """ - if self._logger: - return self._logger - - # Initialise new logger and optionally handlers - logger = logging.getLogger("") - - # Only add one set of handlers - # Exclude from coverage, as pytest will have configured the - # root logger already - if not logger.handlers: # pragma: no cover - fmt = logging.Formatter( - "%(asctime)s %(filename)s:%(lineno)s" " %(levelname)-8s %(message)s", - datefmt="%H:%M:%S", - ) - - logfile = logging.handlers.RotatingFileHandler( - self.logfile, maxBytes=1024 * 1024, backupCount=1 - ) - logfile.setFormatter(fmt) - logger.addHandler(logfile) - - console = logging.StreamHandler() - console.setFormatter(fmt) - logger.addHandler(console) - - if self.debugging: - logger.setLevel(logging.DEBUG) - else: - logger.setLevel(logging.INFO) - - self._logger = logger - - return self._logger - - @logger.setter - def logger(self, logger): - """Set a custom logger. - - :param logger: The logger to use - :type logger: `~logging.Logger` instance - - """ - self._logger = logger - - @property - def settings_path(self): - """Path to settings file within workflow's data directory. - - :returns: path to ``settings.json`` file - :rtype: ``str`` - - """ - if not self._settings_path: - self._settings_path = self.datafile("settings.json") - return self._settings_path - - @property - def settings(self): - """Return a dictionary subclass that saves itself when changed. - - See :ref:`guide-settings` in the :ref:`user-manual` for more - information on how to use :attr:`settings` and **important - limitations** on what it can do. - - :returns: :class:`~workflow.workflow.Settings` instance - initialised from the data in JSON file at - :attr:`settings_path` or if that doesn't exist, with the - ``default_settings`` :class:`dict` passed to - :class:`Workflow` on instantiation. - :rtype: :class:`~workflow.workflow.Settings` instance - - """ - if not self._settings: - self.logger.debug("reading settings from %s", self.settings_path) - self._settings = Settings(self.settings_path, self._default_settings) - return self._settings - - @property - def cache_serializer(self): - """Name of default cache serializer. - - This serializer is used by :meth:`cache_data()` and - :meth:`cached_data()` - - See :class:`SerializerManager` for details. - - :returns: serializer name - :rtype: ``str`` - - """ - return self._cache_serializer - - @cache_serializer.setter - def cache_serializer(self, serializer_name): - """Set the default cache serialization format. - - This serializer is used by :meth:`cache_data()` and - :meth:`cached_data()` - - The specified serializer must already by registered with the - :class:`SerializerManager` at `~workflow.workflow.manager`, - otherwise a :class:`ValueError` will be raised. - - :param serializer_name: Name of default serializer to use. - :type serializer_name: - - """ - if manager.serializer(serializer_name) is None: - raise ValueError( - f"Unknown serializer : `{serializer_name}`. " - "Register your serializer with `manager` first." - ) - - self.logger.debug("default cache serializer: %s", serializer_name) - - self._cache_serializer = serializer_name - - @property - def data_serializer(self): - """Name of default data serializer. - - This serializer is used by :meth:`store_data()` and - :meth:`stored_data()` - - See :class:`SerializerManager` for details. - - :returns: serializer name - :rtype: ``str`` - - """ - return self._data_serializer - - @data_serializer.setter - def data_serializer(self, serializer_name): - """Set the default cache serialization format. - - This serializer is used by :meth:`store_data()` and - :meth:`stored_data()` - - The specified serializer must already by registered with the - :class:`SerializerManager` at `~workflow.workflow.manager`, - otherwise a :class:`ValueError` will be raised. - - :param serializer_name: Name of serializer to use by default. - - """ - if manager.serializer(serializer_name) is None: - raise ValueError( - f"Unknown serializer : `{serializer_name}`. " - "Register your serializer with `manager` first." - ) - - self.logger.debug("default data serializer: %s", serializer_name) - - self._data_serializer = serializer_name - - def stored_data(self, name): - """Retrieve data from data directory. - - Returns ``None`` if there are no data stored under ``name``. - - :param name: name of datastore - - """ - metadata_path = self.datafile(f".{name}.alfred-workflow") - - if not os.path.exists(metadata_path): - self.logger.debug("no data stored for `%s`", name) - return None - - with open(metadata_path, "r", encoding="utf-8") as file_obj: - serializer_name = file_obj.read().strip() - - serializer = manager.serializer(serializer_name) - - if serializer is None: - raise ValueError( - f"Unknown serializer `{serializer_name}`. " - "Register a corresponding serializer with `manager.register()`" - " to load this data." - ) - - self.logger.debug("data `%s` stored as `%s`", name, serializer_name) - - filename = f"{name}.{serializer_name}" - data_path = self.datafile(filename) - - if not os.path.exists(data_path): - self.logger.debug("no data stored: %s", name) - if os.path.exists(metadata_path): - os.unlink(metadata_path) - - return None - - with open(data_path, "rb") as file_obj: - data = serializer.load(file_obj) - - self.logger.debug("stored data loaded: %s", data_path) - - return data - - def store_data(self, name, data, serializer=None): - """Save data to data directory. - - If ``data`` is ``None``, the datastore will be deleted. - - Note that the datastore does NOT support mutliple threads. - - :param name: name of datastore - :param data: object(s) to store. **Note:** some serializers - can only handled certain types of data. - :param serializer: name of serializer to use. If no serializer - is specified, the default will be used. See - :class:`SerializerManager` for more information. - :returns: data in datastore or ``None`` - - """ - # Ensure deletion is not interrupted by SIGTERM - @uninterruptible - def delete_paths(paths): - """Clear one or more data stores""" - for path in paths: - if os.path.exists(path): - os.unlink(path) - self.logger.debug("deleted data file: %s", path) - - serializer_name = serializer or self.data_serializer - - # In order for `stored_data()` to be able to load data stored with - # an arbitrary serializer, yet still have meaningful file extensions, - # the format (i.e. extension) is saved to an accompanying file - metadata_path = self.datafile(f".{name}.alfred-workflow") - filename = f"{name}.{serializer_name}" - data_path = self.datafile(filename) - - if data_path == self.settings_path: - raise ValueError( - "Cannot save data to" - + f"`{name}` with format `{serializer_name}`. " - + "This would overwrite Alfred-Workflow's settings file." - ) - - serializer = manager.serializer(serializer_name) - - if serializer is None: - raise ValueError( - f"Invalid serializer `{serializer_name}`. " - "Register your serializer with `manager.register()` first." - ) - - if data is None: # Delete cached data - delete_paths((metadata_path, data_path)) - return - - if isinstance(data, str): - data = bytearray(data) - - # Ensure write is not interrupted by SIGTERM - @uninterruptible - def _store(): - # Save file extension - with atomic_writer(metadata_path, "w") as file_obj: - file_obj.write(serializer_name) - - with serializer.atomic_writer(data_path, "w") as file_obj: - serializer.dump(data, file_obj) - - _store() - - self.logger.debug("saved data: %s", data_path) - - def cached_data(self, name, data_func=None, max_age=60): - """Return cached data if younger than ``max_age`` seconds. - - Retrieve data from cache or re-generate and re-cache data if - stale/non-existant. If ``max_age`` is 0, return cached data no - matter how old. - - :param name: name of datastore - :param data_func: function to (re-)generate data. - :type data_func: ``callable`` - :param max_age: maximum age of cached data in seconds - :type max_age: ``int`` - :returns: cached data, return value of ``data_func`` or ``None`` - if ``data_func`` is not set - - """ - serializer = manager.serializer(self.cache_serializer) - - cache_path = self.cachefile(f"{name}.{self.cache_serializer}") - age = self.cached_data_age(name) - - if (age < max_age or max_age == 0) and os.path.exists(cache_path): - - with open(cache_path, "rb") as file_obj: - self.logger.debug("loading cached data: %s", cache_path) - return serializer.load(file_obj) - - if not data_func: - return None - - data = data_func() - self.cache_data(name, data) - - return data - - def cache_data(self, name, data): - """Save ``data`` to cache under ``name``. - - If ``data`` is ``None``, the corresponding cache file will be - deleted. - - :param name: name of datastore - :param data: data to store. This may be any object supported by - the cache serializer - - """ - serializer = manager.serializer(self.cache_serializer) - - cache_path = self.cachefile(f"{name}.{self.cache_serializer}") - - if data is None: - if os.path.exists(cache_path): - os.unlink(cache_path) - self.logger.debug("deleted cache file: %s", cache_path) - return - - with serializer.atomic_writer(cache_path, "w") as file_obj: - serializer.dump(data, file_obj) - - self.logger.debug("cached data: %s", cache_path) - - def cached_data_fresh(self, name, max_age): - """Whether cache `name` is less than `max_age` seconds old. - - :param name: name of datastore - :param max_age: maximum age of data in seconds - :type max_age: ``int`` - :returns: ``True`` if data is less than ``max_age`` old, else - ``False`` - - """ - age = self.cached_data_age(name) - - if not age: - return False - - return age < max_age - - def cached_data_age(self, name): - """Return age in seconds of cache `name` or 0 if cache doesn't exist. - - :param name: name of datastore - :type name: ``str`` - :returns: age of datastore in seconds - :rtype: ``int`` - - """ - cache_path = self.cachefile(f"{name}.{self.cache_serializer}") - - if not os.path.exists(cache_path): - return 0 - - return time.time() - os.stat(cache_path).st_mtime - - def filter( - self, - query, - items, - key=lambda x: x, - ascending=False, - include_score=False, - min_score=0, - max_results=0, - match_on=MATCH_ALL, - fold_diacritics=True, - ): - """Fuzzy search filter. Returns list of ``items`` that match ``query``. - - ``query`` is case-insensitive. Any item that does not contain the - entirety of ``query`` is rejected. - - If ``query`` is an empty string or contains only whitespace, - all items will match. - - :param query: query to test items against - :type query: ``str`` - :param items: iterable of items to test - :type items: ``list`` or ``tuple`` - :param key: function to get comparison key from ``items``. - Must return ``str``. The default simply returns - the item. - :type key: ``callable`` - :param ascending: set to ``True`` to get worst matches first - :type ascending: ``Boolean`` - :param include_score: Useful for debugging the scoring algorithm. - If ``True``, results will be a list of tuples - ``(item, score, rule)``. - :type include_score: ``Boolean`` - :param min_score: If non-zero, ignore results with a score lower - than this. - :type min_score: ``int`` - :param max_results: If non-zero, prune results list to this length. - :type max_results: ``int`` - :param match_on: Filter option flags. Bitwise-combined list of - ``MATCH_*`` constants (see below). - :type match_on: ``int`` - :param fold_diacritics: Convert search keys to ASCII-only - characters if ``query`` only contains ASCII characters. - :type fold_diacritics: ``Boolean`` - :returns: list of ``items`` matching ``query`` or list of - ``(item, score, rule)`` `tuples` if ``include_score`` is ``True``. - ``rule`` is the ``MATCH_*`` rule that matched the item. - :rtype: ``list`` - - **Matching rules** - - By default, :meth:`filter` uses all of the following flags (i.e. - :const:`MATCH_ALL`). The tests are always run in the given order: - - 1. :const:`MATCH_STARTSWITH` - Item search key starts with ``query`` (case-insensitive). - 2. :const:`MATCH_CAPITALS` - The list of capital letters in item search key starts with - ``query`` (``query`` may be lower-case). E.g., ``of`` - would match ``OmniFocus``, ``gc`` would match ``Google Chrome``. - 3. :const:`MATCH_ATOM` - Search key is split into "atoms" on non-word characters - (.,-,' etc.). Matches if ``query`` is one of these atoms - (case-insensitive). - 4. :const:`MATCH_INITIALS_STARTSWITH` - Initials are the first characters of the above-described - "atoms" (case-insensitive). - 5. :const:`MATCH_INITIALS_CONTAIN` - ``query`` is a substring of the above-described initials. - 6. :const:`MATCH_INITIALS` - Combination of (4) and (5). - 7. :const:`MATCH_SUBSTRING` - ``query`` is a substring of item search key (case-insensitive). - 8. :const:`MATCH_ALLCHARS` - All characters in ``query`` appear in item search key in - the same order (case-insensitive). - 9. :const:`MATCH_ALL` - Combination of all the above. - - - :const:`MATCH_ALLCHARS` is considerably slower than the other - tests and provides much less accurate results. - - **Examples:** - - To ignore :const:`MATCH_ALLCHARS` (tends to provide the worst - matches and is expensive to run), use - ``match_on=MATCH_ALL ^ MATCH_ALLCHARS``. - - To match only on capitals, use ``match_on=MATCH_CAPITALS``. - - To match only on startswith and substring, use - ``match_on=MATCH_STARTSWITH | MATCH_SUBSTRING``. - - **Diacritic folding** - - If ``fold_diacritics`` is ``True`` (the default), and ``query`` - contains only ASCII characters, non-ASCII characters in search keys - will be converted to ASCII equivalents (e.g. **ü** -> **u**, - **ß** -> **ss**, **é** -> **e**). - - See :const:`ASCII_REPLACEMENTS` for all replacements. - - If ``query`` contains non-ASCII characters, search keys will not be - altered. - - """ - if not query: - return items - - # Remove preceding/trailing spaces - query = query.strip() - - if not query: - return items - - # Use user override if there is one - fold_diacritics = self.settings.get( - "__workflow_diacritic_folding", fold_diacritics - ) - - results = [] - - for item in items: - skip = False - score = 0 - words = [s.strip() for s in query.split(" ")] - value = key(item).strip() - if value == "": - continue - for word in words: - if word == "": - continue - score_, rule = self._filter_item(value, word, match_on, fold_diacritics) - - if not score_: # Skip items that don't match part of the query - skip = True - score += score_ - - if skip: - continue - - if score: - # use "reversed" `score` (i.e. highest becomes lowest) and - # `value` as sort key. This means items with the same score - # will be sorted in alphabetical not reverse alphabetical order - results.append( - ((100.0 / score, value.lower(), score), (item, score, rule)) - ) - - # sort on keys, then discard the keys - results.sort(reverse=ascending) - results = [result[1] for result in results] - - if min_score: - results = [result for result in results if result[1] > min_score] - - if max_results and len(results) > max_results: - results = results[:max_results] - - # return list of ``(item, score, rule)`` - if include_score: - return results - # just return list of items - return [result[0] for result in results] - - def _filter_item(self, value, query, match_on, fold_diacritics): - """Filter ``value`` against ``query`` using rules ``match_on``. - - :returns: ``(score, rule)`` - - """ - query = query.lower() - - if not isascii(query): - fold_diacritics = False - - if fold_diacritics: - value = self.fold_to_ascii(value) - - # pre-filter any items that do not contain all characters - # of ``query`` to save on running several more expensive tests - if not set(query) <= set(value.lower()): - - return (0, None) - - # item starts with query - if match_on & MATCH_STARTSWITH and value.lower().startswith(query): - score = 100.0 - (len(value) / len(query)) - - return (score, MATCH_STARTSWITH) - - # query matches capitalised letters in item, - # e.g. of = OmniFocus - if match_on & MATCH_CAPITALS: - initials = "".join([c for c in value if c in INITIALS]) - if initials.lower().startswith(query): - score = 100.0 - (len(initials) / len(query)) - - return (score, MATCH_CAPITALS) - - # split the item into "atoms", i.e. words separated by - # spaces or other non-word characters - if ( - match_on & MATCH_ATOM - or match_on & MATCH_INITIALS_CONTAIN - or match_on & MATCH_INITIALS_STARTSWITH - ): - atoms = [s.lower() for s in split_on_delimiters(value)] - # initials of the atoms - initials = "".join([s[0] for s in atoms if s]) - - if match_on & MATCH_ATOM: - # is `query` one of the atoms in item? - # similar to substring, but scores more highly, as it's - # a word within the item - if query in atoms: - score = 100.0 - (len(value) / len(query)) - - return (score, MATCH_ATOM) - - # `query` matches start (or all) of the initials of the - # atoms, e.g. ``himym`` matches "How I Met Your Mother" - # *and* "how i met your mother" (the ``capitals`` rule only - # matches the former) - if match_on & MATCH_INITIALS_STARTSWITH and initials.startswith(query): - score = 100.0 - (len(initials) / len(query)) - - return (score, MATCH_INITIALS_STARTSWITH) - - # `query` is a substring of initials, e.g. ``doh`` matches - # "The Dukes of Hazzard" - if match_on & MATCH_INITIALS_CONTAIN and query in initials: - score = 95.0 - (len(initials) / len(query)) - - return (score, MATCH_INITIALS_CONTAIN) - - # `query` is a substring of item - if match_on & MATCH_SUBSTRING and query in value.lower(): - score = 90.0 - (len(value) / len(query)) - - return (score, MATCH_SUBSTRING) - - # finally, assign a score based on how close together the - # characters in `query` are in item. - if match_on & MATCH_ALLCHARS: - search = self._search_for_query(query) - match = search(value) - if match: - score = 100.0 / ( - (1 + match.start()) * (match.end() - match.start() + 1) - ) - - return (score, MATCH_ALLCHARS) - - # Nothing matched - return (0, None) - - def _search_for_query(self, query): - if query in self._search_pattern_cache: - return self._search_pattern_cache[query] - - # Build pattern: include all characters - pattern = [] - for char in query: - pattern.append(f".*?{re.escape(char)}") - pattern = "".join(pattern) - search = re.compile(pattern, re.IGNORECASE).search - - self._search_pattern_cache[query] = search - return search - - def run(self, func, text_errors=False): - """Call ``func`` to run your workflow. - - :param func: Callable to call with ``self`` (i.e. the :class:`Workflow` - instance) as first argument. - :param text_errors: Emit error messages in plain text, not in - Alfred's XML/JSON feedback format. Use this when you're not - running Alfred-Workflow in a Script Filter and would like - to pass the error message to, say, a notification. - :type text_errors: ``Boolean`` - - ``func`` will be called with :class:`Workflow` instance as first - argument. - - ``func`` should be the main entry point to your workflow. - - Any exceptions raised will be logged and an error message will be - output to Alfred. - - """ - start = time.time() - - # Write to debugger to ensure "real" output starts on a new line - print(".", file=sys.stderr) - - # Call workflow's entry function/method within a try-except block - # to catch any errors and display an error message in Alfred - try: - if self.version: - self.logger.debug( - "---------- %s (%s) ----------", self.name, self.version - ) - else: - self.logger.debug("---------- %s ----------", self.name) - - # Run update check if configured for self-updates. - # This call has to go in the `run` try-except block, as it will - # initialise `self.settings`, which will raise an exception - # if `settings.json` isn't valid. - if self._update_settings: - self.check_update() - - # Run workflow's entry function/method - func(self) - - # Set last version run to current version after a successful - # run - self.set_last_version() - - except Exception as err: # pylint: disable=broad-except - self.logger.exception(err) - if self.help_url: - self.logger.info("for assistance, see: %s", self.help_url) - - if not sys.stdout.isatty(): # Show error in Alfred - if text_errors: - print(str(err).encode("utf-8"), end="") - else: - self._items = [] - if self._name: - name = self._name - elif self._bundleid: # pragma: no cover - name = self._bundleid - else: # pragma: no cover - name = os.path.dirname(__file__) - self.add_item( - f"Error in workflow '{name}'", str(err), icon=ICON_ERROR - ) - self.send_feedback() - return 1 - - finally: - self.logger.debug( - "---------- finished in %0.3fs ----------", time.time() - start - ) - - return 0 - - # Alfred feedback methods ------------------------------------------ - - @property - def rerun(self): - """How often (in seconds) Alfred should re-run the Script Filter.""" - return self._rerun - - @rerun.setter - def rerun(self, seconds): - """Interval at which Alfred should re-run the Script Filter. - - Args: - seconds (int): Interval between runs. - """ - self._rerun = seconds - - @property - def session_id(self): - """A unique session ID every time the user uses the workflow. - - The session ID persists while the user is using this workflow. - It expires when the user runs a different workflow or closes - Alfred. - - """ - if not self._session_id: - self._session_id = uuid4().hex - self.setvar("_WF_SESSION_ID", self._session_id) - - return self._session_id - - def setvar(self, name, value, persist=False): - """Set a "global" workflow variable. - - .. versionchanged:: 1.33 - - These variables are always passed to downstream workflow objects. - - If you have set :attr:`rerun`, these variables are also passed - back to the script when Alfred runs it again. - - Args: - name (str): Name of variable. - value (str): Value of variable. - persist (bool, optional): Also save variable to ``info.plist``? - - """ - self.variables[name] = value - if persist: - set_config(name, value, self.bundleid) - self.logger.debug( - "saved variable %r with value %r to info.plist", name, value - ) - - def getvar(self, name, default=None): - """Return value of workflow variable for ``name`` or ``default``. - - Args: - name (str): Variable name. - default (None, optional): Value to return if variable is unset. - - Returns: - str or ``default``: Value of variable if set or ``default``. - - """ - return self.variables.get(name, default) - - def add_item( - self, - title, - subtitle="", - arg=None, - autocomplete=None, - valid=False, - uid=None, - icon=None, - icontype=None, - type=None, # pylint: disable=redefined-builtin - largetext=None, - copytext=None, - quicklookurl=None, - match=None, - ): - """Add an item to be output to Alfred. - - :param title: Title shown in Alfred. - :type title: ``str`` - :param subtitle: Subtitle shown in Alfred. - :type subtitle: ``str`` - :param arg: Argument passed by Alfred as ``{query}`` when item is - actioned. - :type arg: ``str``, ``list`` or ``tuple`` - :param autocomplete: Text expanded in Alfred when item is TABbed. - :type autocomplete: ``str`` - :param valid: Whether or not item can be actioned. - :type valid: ``Boolean`` - :param uid: Used by Alfred to remember/sort items. - :type uid: ``str`` - :param icon: Filename of icon to use. - :type icon: ``str`` - :param icontype: Type of icon. Must be one of ``None``, ``'filetype'`` - or ``'fileicon'``. Use ``'filetype'`` when ``icon`` is a filetype - such as ``'public.folder'``. Use ``'fileicon'`` when you wish to - use the icon of the file specified as ``icon``, e.g. - ``icon='/Applications/Safari.app', icontype='fileicon'``. - Leave as `None` if ``icon`` points to an actual icon file. - :type icontype: ``str`` - :param type: Result type. Currently only ``'file'`` is supported - (by Alfred). This will tell Alfred to enable file actions for - this item. - :type type: ``str`` - :param largetext: Text to be displayed in Alfred's large text box - if user presses CMD+L on item. - :type largetext: ``str`` - :param copytext: Text to be copied to pasteboard if user presses - CMD+C on item. - :type copytext: ``str`` - :param quicklookurl: URL to be displayed using Alfred's Quick Look - feature (tapping ``SHIFT`` or ``⌘+Y`` on a result). - :type quicklookurl: ``str`` - :param match: If you have "Alfred filters results" turned on for - your Script Filter, Alfred will filter against this field, not - ``title``. - :type match: ``str`` - :returns: :class:`Item` instance - - See :ref:`icons` for a list of the supported system icons. - - .. note:: - - Although this method returns an :class:`Item` instance, you don't - need to hold onto it or worry about it. All generated :class:`Item` - instances are also collected internally and sent to Alfred when - :meth:`send_feedback` is called. - - The generated :class:`Item` is only returned in case you want to - edit it or do something with it other than send it to Alfred. - - """ - item = self.item_class( - title, - subtitle, - arg, - autocomplete, - match, - valid, - uid, - icon, - icontype, - type, - largetext, - copytext, - quicklookurl, - ) - - # Add variables to child item - item.variables.update(self.variables) - - self._items.append(item) - return item - - @property - def obj(self): - """Feedback formatted for JSON serialization. - - Returns: - dict: Data suitable for Alfred feedback. - - """ - items = [] - for item in self._items: - items.append(item.obj) - - obj_ = {"items": items} - if self.variables: - obj_["variables"] = self.variables - if self.rerun: - obj_["rerun"] = self.rerun - return obj_ - - def warn_empty(self, title, subtitle="", icon=None): - """Add a warning to feedback if there are no items. - - Add a warning item to Alfred feedback if no other items - have been added. This is a handy shortcut to prevent Alfred - from showing its fallback searches, which it does if no - items are returned. - - Args: - title (str): Title of feedback item. - subtitle (str, optional): Subtitle of feedback item. - icon (str, optional): Icon for feedback item. If not - specified, ``ICON_ERROR`` is used. - - Returns: - Item: Newly-created item. - - """ - if self._items: - return None - - icon = icon or ICON_ERROR - return self.add_item(title, subtitle, icon=icon) - - def send_feedback(self): - """Print stored items to console/Alfred as JSON.""" - if self.debugging: - json.dump(self.obj, sys.stdout, indent=2, separators=(",", ": ")) - else: - json.dump(self.obj, sys.stdout) - sys.stdout.flush() - - #################################################################### - # Updating methods - #################################################################### - - @property - def first_run(self): - """Return ``True`` if it's the first time this version has run. - - Raises a :class:`ValueError` if :attr:`version` isn't set. - - """ - if not self.version: - raise ValueError("No workflow version set") - - if not self.last_version_run: - return True - - return self.version != self.last_version_run - - @property - def last_version_run(self): - """Return version of last version to run (or ``None``). - - :returns: :class:`~workflow.update.Version` instance - or ``None`` - - """ - if self._last_version_run is UNSET: - - version = self.settings.get("__workflow_last_version") - if version: - version = Version(version) - - self._last_version_run = version - - self.logger.debug("last run version: %s", self._last_version_run) - - return self._last_version_run - - def set_last_version(self, version=None): - """Set :attr:`last_version_run` to current version. - - :param version: version to store (default is current version) - :type version: :class:`~workflow.update.Version` instance - or ``str`` - :returns: ``True`` if version is saved, else ``False`` - - """ - if not version: - if not self.version: - self.logger.warning("Can't save last version: workflow has no version") - return False - - version = self.version - - if isinstance(version, str): - version = Version(version) - - self.settings["__workflow_last_version"] = str(version) - - self.logger.debug("set last run version: %s", version) - - return True - - @property - def update_available(self): - """Whether an update is available. - - See :ref:`guide-updates` in the :ref:`user-manual` for detailed - information on how to enable your workflow to update itself. - - :returns: ``True`` if an update is available, else ``False`` - - """ - key = "__workflow_latest_version" - # Create a new workflow object to ensure standard serialiser - # is used (update.py is called without the user's settings) - status = Workflow().cached_data(key, max_age=0) - - if not status or not status.get("available"): - return False - - return status["available"] - - @property - def prereleases(self): - """Whether workflow should update to pre-release versions. - - :returns: ``True`` if pre-releases are enabled with the :ref:`magic - argument ` or the ``update_settings`` dict, else - ``False``. - - """ - if self._update_settings.get("prereleases"): - return True - - return self.settings.get("__workflow_prereleases") or False - - def check_update(self, force=False): - """Call update script if it's time to check for a new release. - - The update script will be run in the background, so it won't - interfere in the execution of your workflow. - - See :ref:`guide-updates` in the :ref:`user-manual` for detailed - information on how to enable your workflow to update itself. - - :param force: Force update check - :type force: ``Boolean`` - - """ - key = "__workflow_latest_version" - frequency = self._update_settings.get("frequency", DEFAULT_UPDATE_FREQUENCY) - - if not force and not self.settings.get("__workflow_autoupdate", True): - self.logger.debug("Auto update turned off by user") - return - - # Check for new version if it's time - if force or not self.cached_data_fresh(key, frequency * 86400): - - repo = self._update_settings["github_slug"] - version = str(self.version) - - from .background import run_in_background - - cmd = ["/usr/bin/python3", "-m", "workflow.update", "check", repo, version] - - if self.prereleases: - cmd.append("--prereleases") - - self.logger.info("checking for update ...") - - run_in_background("__workflow_update_check", cmd) - - else: - self.logger.debug("update check not due") - - def start_update(self): - """Check for update and download and install new workflow file. - - See :ref:`guide-updates` in the :ref:`user-manual` for detailed - information on how to enable your workflow to update itself. - - :returns: ``True`` if an update is available and will be - installed, else ``False`` - - """ - repo = self._update_settings["github_slug"] - version = str(self.version) - - if not update.check_update(repo, version, self.prereleases): - return False - - from .background import run_in_background - - cmd = ["/usr/bin/python3", "-m", "workflow.update", "install", repo, version] - - if self.prereleases: - cmd.append("--prereleases") - - self.logger.debug("downloading update ...") - run_in_background("__workflow_update_install", cmd) - - return True - - #################################################################### - # Keychain password storage methods - #################################################################### - - def save_password(self, account, password, service=None): - """Save account credentials. - If the account exists, the old password will first be deleted - (Keychain throws an error otherwise). - If something goes wrong, a :class:`KeychainError` exception will - be raised. - :param account: name of the account the password is for, e.g. - "Pinboard" - :type account: ``str`` - :param password: the password to secure - :type password: ``str`` - :param service: Name of the service. By default, this is the - workflow's bundle ID - :type service: ``str`` - """ - if not service: - service = self.bundleid - - try: - self._call_security( - "add-generic-password", service, account, "-w", password - ) - self.logger.debug("saved password : %s:%s", service, account) - - except PasswordExists: - self.logger.debug("password exists : %s:%s", service, account) - current_password = self.get_password(account, service) - - if current_password == password: - self.logger.debug("password unchanged") - - else: - self.delete_password(account, service) - self._call_security( - "add-generic-password", service, account, "-w", password - ) - self.logger.debug("save_password : %s:%s", service, account) - - def get_password(self, account, service=None): - """Retrieve the password saved at ``service/account``. - Raise :class:`PasswordNotFound` exception if password doesn't exist. - :param account: name of the account the password is for, e.g. - "Pinboard" - :type account: ``str`` - :param service: Name of the service. By default, this is the workflow's - bundle ID - :type service: ``str`` - :returns: account password - :rtype: ``str`` - """ - if not service: - service = self.bundleid - - output = self._call_security("find-generic-password", service, account, "-g") - - # Parsing of `security` output is adapted from python-keyring - # by Jason R. Coombs - # https://pypi.python.org/pypi/keyring - match = re.search( - r'password:\s*(?:0x(?P[0-9A-F]+)\s*)?(?:"(?P.*)")?', output - ) - - if match: - groups = match.groupdict() - hex_ = groups.get("hex") - password = groups.get("pw") - if hex_: - password = str(binascii.unhexlify(hex_), "utf-8") - - self.logger.debug("got password : %s:%s", service, account) - - return password - - def delete_password(self, account, service=None): - """Delete the password stored at ``service/account``. - Raise :class:`PasswordNotFound` if account is unknown. - :param account: name of the account the password is for, e.g. - "Pinboard" - :type account: ``str`` - :param service: Name of the service. By default, this is the workflow's - bundle ID - :type service: ``str`` - """ - if not service: - service = self.bundleid - - self._call_security("delete-generic-password", service, account) - - self.logger.debug("deleted password : %s:%s", service, account) - - #################################################################### - # Methods for workflow:* magic args - #################################################################### - - def _register_default_magic(self): - """Register the built-in magic arguments.""" - # TODO: refactor & simplify - # Wrap callback and message with callable - def callback(func, msg): - def wrapper(): - func() - return msg - - return wrapper - - self.magic_arguments["delcache"] = callback( - self.clear_cache, "Deleted workflow cache" - ) - self.magic_arguments["deldata"] = callback( - self.clear_data, "Deleted workflow data" - ) - self.magic_arguments["delsettings"] = callback( - self.clear_settings, "Deleted workflow settings" - ) - self.magic_arguments["reset"] = callback(self.reset, "Reset workflow") - self.magic_arguments["openlog"] = callback( - self.open_log, "Opening workflow log file" - ) - self.magic_arguments["opencache"] = callback( - self.open_cachedir, "Opening workflow cache directory" - ) - self.magic_arguments["opendata"] = callback( - self.open_datadir, "Opening workflow data directory" - ) - self.magic_arguments["openworkflow"] = callback( - self.open_workflowdir, "Opening workflow directory" - ) - self.magic_arguments["openterm"] = callback( - self.open_terminal, "Opening workflow root directory in Terminal" - ) - - # Diacritic folding - def fold_on(): - self.settings["__workflow_diacritic_folding"] = True - return "Diacritics will always be folded" - - def fold_off(): - self.settings["__workflow_diacritic_folding"] = False - return "Diacritics will never be folded" - - def fold_default(): - if "__workflow_diacritic_folding" in self.settings: - del self.settings["__workflow_diacritic_folding"] - return "Diacritics folding reset" - - self.magic_arguments["foldingon"] = fold_on - self.magic_arguments["foldingoff"] = fold_off - self.magic_arguments["foldingdefault"] = fold_default - - # Updates - def update_on(): - self.settings["__workflow_autoupdate"] = True - return "Auto update turned on" - - def update_off(): - self.settings["__workflow_autoupdate"] = False - return "Auto update turned off" - - def prereleases_on(): - self.settings["__workflow_prereleases"] = True - return "Prerelease updates turned on" - - def prereleases_off(): - self.settings["__workflow_prereleases"] = False - return "Prerelease updates turned off" - - def do_update(): - if self.start_update(): - return "Downloading and installing update ..." - - return "No update available" - - self.magic_arguments["autoupdate"] = update_on - self.magic_arguments["noautoupdate"] = update_off - self.magic_arguments["prereleases"] = prereleases_on - self.magic_arguments["noprereleases"] = prereleases_off - self.magic_arguments["update"] = do_update - - # Help - def do_help(): - if self.help_url: - self.open_help() - return "Opening workflow help URL in browser" - - return "Workflow has no help URL" - - def show_version(): - if self.version: - return f"Version: {self.version}" - - return "This workflow has no version number" - - def list_magic(): - """Display all available magic args in Alfred.""" - isatty = sys.stderr.isatty() - for name in sorted(self.magic_arguments.keys()): - if name == "magic": - continue - arg = self.magic_prefix + name - self.logger.debug(arg) - - if not isatty: - self.add_item(arg, icon=ICON_INFO) - - if not isatty: - self.send_feedback() - - self.magic_arguments["help"] = do_help - self.magic_arguments["magic"] = list_magic - self.magic_arguments["version"] = show_version - - def clear_cache(self, filter_func=lambda f: True): - """Delete all files in workflow's :attr:`cachedir`. - - :param filter_func: Callable to determine whether a file should be - deleted or not. ``filter_func`` is called with the filename - of each file in the data directory. If it returns ``True``, - the file will be deleted. - By default, *all* files will be deleted. - :type filter_func: ``callable`` - """ - self._delete_directory_contents(self.cachedir, filter_func) - - def clear_data(self, filter_func=lambda f: True): - """Delete all files in workflow's :attr:`datadir`. - - :param filter_func: Callable to determine whether a file should be - deleted or not. ``filter_func`` is called with the filename - of each file in the data directory. If it returns ``True``, - the file will be deleted. - By default, *all* files will be deleted. - :type filter_func: ``callable`` - """ - self._delete_directory_contents(self.datadir, filter_func) - - def clear_settings(self): - """Delete workflow's :attr:`settings_path`.""" - if os.path.exists(self.settings_path): - os.unlink(self.settings_path) - self.logger.debug("deleted : %r", self.settings_path) - - def reset(self): - """Delete workflow settings, cache and data. - - File :attr:`settings ` and directories - :attr:`cache ` and :attr:`data ` are deleted. - - """ - self.clear_cache() - self.clear_data() - self.clear_settings() - - def open_log(self): - """Open :attr:`logfile` in default app (usually Console.app).""" - subprocess.run(["/usr/bin/open", self.logfile], check=True) - - def open_cachedir(self): - """Open the workflow's :attr:`cachedir` in Finder.""" - subprocess.run(["/usr/bin/open", self.cachedir], check=True) - - def open_datadir(self): - """Open the workflow's :attr:`datadir` in Finder.""" - subprocess.run(["/usr/bin/open", self.datadir], check=True) - - def open_workflowdir(self): - """Open the workflow's :attr:`workflowdir` in Finder.""" - subprocess.run(["/usr/bin/open", self.workflowdir], check=True) - - def open_terminal(self): - """Open a Terminal window at workflow's :attr:`workflowdir`.""" - subprocess.run( - ["/usr/bin/open", "-a", "Terminal", self.workflowdir], check=True - ) - - def open_help(self): - """Open :attr:`help_url` in default browser.""" - subprocess.run(["/usr/bin/open", self.help_url], check=True) - - return "Opening workflow help URL in browser" - - #################################################################### - # Helper methods - #################################################################### - - def decode(self, text, encoding=None, normalization=None): - """Return ``text`` as normalised unicode. - If ``encoding`` and/or ``normalization`` is ``None``, the - ``input_encoding``and ``normalization`` parameters passed to - :class:`Workflow` are used. - :param text: string - :type text: encoded or Unicode string. If ``text`` is already a - Unicode string, it will only be normalised. - :param encoding: The text encoding to use to decode ``text`` to - Unicode. - :type encoding: ``str`` or ``None`` - :param normalization: The nomalisation form to apply to ``text``. - :type normalization: ``str`` or ``None`` - :returns: decoded and normalised ``str`` - :class:`Workflow` uses "NFC" normalization by default. This is the - standard for Python and will work well with data from the web (via - :mod:`~workflow.web` or :mod:`json`). - macOS, on the other hand, uses "NFD" normalization (nearly), so data - coming from the system (e.g. via :mod:`subprocess` or - :func:`os.listdir`/:mod:`os.path`) may not match. You should either - normalise this data, too, or change the default normalization used by - :class:`Workflow`. - """ - encoding = encoding or self._input_encoding - normalization = normalization or self._normalization - if not isinstance(text, str): - text = str(text, encoding) - return unicodedata.normalize(normalization, text) - - @staticmethod - def fold_to_ascii(text): - """Convert non-ASCII characters to closest ASCII equivalent. - .. note:: This only works for a subset of European languages. - :param text: text to convert - :type text: ``str`` - :returns: text containing only ASCII characters - :rtype: ``str`` - """ - if isascii(text): - return text - text = "".join([ASCII_REPLACEMENTS.get(c, c) for c in text]) - return unicodedata.normalize("NFKD", text) - - @staticmethod - def dumbify_punctuation(text): - """Convert non-ASCII punctuation to closest ASCII equivalent. - This method replaces "smart" quotes and n- or m-dashes with their - workaday ASCII equivalents. This method is currently not used - internally, but exists as a helper method for workflow authors. - :param text: text to convert - :type text: ``str`` - :returns: text with only ASCII punctuation - :rtype: ``str`` - """ - if isascii(text): - return text - - text = "".join([DUMB_PUNCTUATION.get(c, c) for c in text]) - return text - - def _delete_directory_contents(self, dirpath, filter_func): - """Delete all files in a directory. - :param dirpath: path to directory to clear - :type dirpath: ``str`` - :param filter_func function to determine whether a file shall be - deleted or not. - :type filter_func ``callable`` - """ - if os.path.exists(dirpath): - for filename in os.listdir(dirpath): - if not filter_func(filename): - continue - path = os.path.join(dirpath, filename) - if os.path.isdir(path): - shutil.rmtree(path) - else: - os.unlink(path) - self.logger.debug("deleted: %s", path) - - def _load_info_plist(self): - """Load workflow info from ``info.plist``.""" - # info.plist should be in the directory above this one - with open(self.workflowfile("info.plist"), "rb") as file_obj: - self._info = plistlib.load(file_obj) - self._info_loaded = True - - @staticmethod - def _create(dirpath): - """Create directory `dirpath` if it doesn't exist. - :param dirpath: path to directory - :type dirpath: ``str`` - :returns: ``dirpath`` argument - :rtype: ``str`` - """ - if not os.path.exists(dirpath): - os.makedirs(dirpath) - return dirpath - - @staticmethod - def _call_security(action, service, account, *args): - """Call ``security`` CLI program that provides access to keychains. - May raise `PasswordNotFound`, `PasswordExists` or `KeychainError` - exceptions (the first two are subclasses of `KeychainError`). - :param action: The ``security`` action to call, e.g. - ``add-generic-password`` - :type action: ``str`` - :param service: Name of the service. - :type service: ``str`` - :param account: name of the account the password is for, e.g. - "Pinboard" - :type account: ``str`` - :param password: the password to secure - :type password: ``str`` - :param *args: list of command line arguments to be passed to - ``security`` - :type *args: `list` or `tuple` - :returns: Data from stdout. - :rtype: ``str`` - """ - cmd = ["security", action, "-s", service, "-a", account] + list(args) - with subprocess.Popen( - cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT - ) as proc: - stdout, _ = proc.communicate() - if proc.returncode == 44: # password does not exist - raise PasswordNotFound() - if proc.returncode == 45: # password already exists - raise PasswordExists() - if proc.returncode > 0: - err = KeychainError(f"Unknown Keychain error : {stdout}") - raise err - return stdout.strip().decode("utf-8") diff --git a/src/lib/zothero/core.py b/src/lib/zothero/core.py index 062dc65..b607e5f 100644 --- a/src/lib/zothero/core.py +++ b/src/lib/zothero/core.py @@ -149,7 +149,7 @@ def index(self): if not self._index: from .index import Index self._index = Index(os.path.join(self.cachedir, 'search.sqlite')) - # self._index.update(self.zotero) + self._index.update(self.zotero) return self._index

d(Y?yC0WcM~e9ZwXO6oO?gWv;#WPIjHc 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 z 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