Skip to content

Commit

Permalink
MOD: upgrade to support sierra
Browse files Browse the repository at this point in the history
  • Loading branch information
zhangyc committed Aug 11, 2017
1 parent 6d74a55 commit ede22e1
Show file tree
Hide file tree
Showing 12 changed files with 1,633 additions and 644 deletions.
221 changes: 174 additions & 47 deletions info.plist

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.2.4
1.2.5
Empty file added workflow/.alfredversionchecked
Empty file.
Binary file added workflow/Notify.tgz
Binary file not shown.
22 changes: 11 additions & 11 deletions workflow/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,13 @@
# Created on 2014-02-15
#

"""
A Python helper library for `Alfred 2 <http://www.alfredapp.com/>`_ Workflow
authors.
"""
"""A helper library for `Alfred <http://www.alfredapp.com/>`_ workflows."""

import os

__title__ = 'Alfred-Workflow'
__version__ = open(os.path.join(os.path.dirname(__file__), 'version')).read()
__author__ = 'Dean Jackson'
__licence__ = 'MIT'
__copyright__ = 'Copyright 2014 Dean Jackson'


# Workflow objects
from .workflow import Workflow, manager
from .workflow3 import Variables, Workflow3

# Exceptions
from .workflow import PasswordNotFound, KeychainError
Expand Down Expand Up @@ -68,8 +59,17 @@
MATCH_SUBSTRING,
)


__title__ = 'Alfred-Workflow'
__version__ = open(os.path.join(os.path.dirname(__file__), 'version')).read()
__author__ = 'Dean Jackson'
__licence__ = 'MIT'
__copyright__ = 'Copyright 2014-2017 Dean Jackson'

__all__ = [
'Variables',
'Workflow',
'Workflow3',
'manager',
'PasswordNotFound',
'KeychainError',
Expand Down
105 changes: 52 additions & 53 deletions workflow/background.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@
#

"""
Run background tasks
This module provides an API to run commands in background processes.
Combine with the :ref:`caching API <caching-data>` to work from cached data
while you fetch fresh data in the background.
See :ref:`the User Manual <background-processes>` for more information
and examples.
"""

from __future__ import print_function, unicode_literals
Expand All @@ -33,41 +38,43 @@ def wf():
return _wf


def _log():
return wf().logger


def _arg_cache(name):
"""Return path to pickle cache file for arguments
"""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('{0}.argcache'.format(name))
return wf().cachefile(name + '.argcache')


def _pid_file(name):
"""Return path to PID file for ``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('{0}.pid'.format(name))
return wf().cachefile(name + '.pid')


def _process_exists(pid):
"""Check if a process with PID ``pid`` exists
"""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
Expand All @@ -76,13 +83,12 @@ def _process_exists(pid):


def is_running(name):
"""
Test whether task is running under ``name``
"""Test whether task ``name`` is currently running.
:param name: name of task
:type name: ``unicode``
:type name: unicode
:returns: ``True`` if task with name ``name`` is running, else ``False``
:rtype: ``Boolean``
:rtype: bool
"""
pidfile = _pid_file(name)
Expand Down Expand Up @@ -113,34 +119,30 @@ def _background(stdin='/dev/null', stdout='/dev/null',
:type stderr: filepath
"""
def _fork_and_exit_parent(errmsg):
try:
pid = os.fork()
if pid > 0:
os._exit(0)
except OSError as err:
_log().critical('%s: (%d) %s', errmsg, err.errno, err.strerror)
raise err

# Do first fork.
try:
pid = os.fork()
if pid > 0:
sys.exit(0) # Exit first parent.
except OSError as e:
wf().logger.critical("fork #1 failed: ({0:d}) {1}".format(
e.errno, e.strerror))
sys.exit(1)
_fork_and_exit_parent('fork #1 failed')

# Decouple from parent environment.
os.chdir(wf().workflowdir)
os.umask(0)
os.setsid()

# Do second fork.
try:
pid = os.fork()
if pid > 0:
sys.exit(0) # Exit second parent.
except OSError as e:
wf().logger.critical("fork #2 failed: ({0:d}) {1}".format(
e.errno, e.strerror))
sys.exit(1)
_fork_and_exit_parent('fork #2 failed')

# Now I am a daemon!
# Redirect standard file descriptors.
si = file(stdin, 'r', 0)
so = file(stdout, 'a+', 0)
se = file(stderr, 'a+', 0)
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'):
Expand All @@ -150,15 +152,14 @@ def _background(stdin='/dev/null', stdout='/dev/null',


def run_in_background(name, args, **kwargs):
"""Pickle arguments to cache file, then call this script again via
:func:`subprocess.call`.
r"""Cache arguments then call this script again via :func:`subprocess.call`.
:param name: name of task
:type name: ``unicode``
: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``
: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
Expand All @@ -175,40 +176,40 @@ def run_in_background(name, args, **kwargs):
return immediately and will not run the specified command.
"""

if is_running(name):
wf().logger.info('Task `{0}` is already running'.format(name))
_log().info('[%s] job already running', name)
return

argcache = _arg_cache(name)

# Cache arguments
with open(argcache, 'wb') as file_obj:
pickle.dump({'args': args, 'kwargs': kwargs}, file_obj)
wf().logger.debug('Command arguments cached to `{0}`'.format(argcache))
_log().debug('[%s] command cached: %s', name, argcache)

# Call this script
cmd = ['/usr/bin/python', __file__, name]
wf().logger.debug('Calling {0!r} ...'.format(cmd))
_log().debug('[%s] passing job to background runner: %r', name, cmd)
retcode = subprocess.call(cmd)
if retcode: # pragma: no cover
wf().logger.error('Failed to call task in background')
_log().error('[%s] background runner failed with %d', retcode)
else:
wf().logger.debug('Executing task `{0}` in background...'.format(name))
_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
:meth:`subprocess.call` with cached arguments.
"""

log = wf.logger
name = wf.args[0]
argcache = _arg_cache(name)
if not os.path.exists(argcache):
wf.logger.critical('No arg cache found : {0!r}'.format(argcache))
log.critical('[%s] command cache not found: %r', name, argcache)
return 1

# Load cached arguments
Expand All @@ -229,23 +230,21 @@ def main(wf): # pragma: no cover

# Write PID to file
with open(pidfile, 'wb') as file_obj:
file_obj.write('{0}'.format(os.getpid()))
file_obj.write(str(os.getpid()))

# Run the command
try:
wf.logger.debug('Task `{0}` running'.format(name))
wf.logger.debug('cmd : {0!r}'.format(args))
log.debug('[%s] running command: %r', name, args)

retcode = subprocess.call(args, **kwargs)

if retcode:
wf.logger.error('Command failed with [{0}] : {1!r}'.format(
retcode, args))
log.error('[%s] command failed with status %d', name, retcode)

finally:
if os.path.exists(pidfile):
os.unlink(pidfile)
wf.logger.debug('Task `{0}` finished'.format(name))
log.debug('[%s] job complete', name)


if __name__ == '__main__': # pragma: no cover
Expand Down
Loading

0 comments on commit ede22e1

Please sign in to comment.