Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

升级workflows #42

Merged
merged 2 commits into from
Jul 3, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# whyliam.workflows.youdao

## 有道翻译 workflow v2.0.0
## 有道翻译 workflow v2.0.1

默认快捷键 `yd`,查看翻译结果。

Expand All @@ -20,7 +20,7 @@

### 下载

[点击下载](https://github.com/liszd/whyliam.workflows.youdao/releases/download/2.0.0/whyliam.workflows.youdao.alfredworkflow)
[点击下载](https://github.com/liszd/whyliam.workflows.youdao/releases/download/2.0.1/whyliam.workflows.youdao.alfredworkflow)

### 安装

Expand Down
2 changes: 1 addition & 1 deletion info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@
</dict>
</array>
<key>readme</key>
<string>有道翻译 Workflow v2.0.0
<string>有道翻译 Workflow v2.0.1

默认快捷键 yd, 查看翻译结果。

Expand Down
2 changes: 1 addition & 1 deletion version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.0.0
2.0.1
Binary file modified whyliam.workflows.youdao.alfredworkflow
Binary file not shown.
3 changes: 2 additions & 1 deletion workflow/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

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

# Exceptions
from .workflow import PasswordNotFound, KeychainError
Expand Down Expand Up @@ -67,6 +67,7 @@
__copyright__ = 'Copyright 2014 Dean Jackson'

__all__ = [
'Variables',
'Workflow',
'Workflow3',
'manager',
Expand Down
38 changes: 18 additions & 20 deletions workflow/background.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,33 +108,31 @@ 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:
wf().logger.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 Down
4 changes: 2 additions & 2 deletions workflow/update.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,8 @@ def download_workflow(url):
"""
filename = url.split("/")[-1]

if (not url.endswith('.alfredworkflow') or
not filename.endswith('.alfredworkflow')):
if (not filename.endswith('.alfredworkflow') and
not filename.endswith('.alfred3workflow')):
raise ValueError('Attachment `{0}` not a workflow'.format(filename))

local_path = os.path.join(tempfile.gettempdir(), filename)
Expand Down
2 changes: 1 addition & 1 deletion workflow/version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.24
1.26
84 changes: 62 additions & 22 deletions workflow/workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

from __future__ import print_function, unicode_literals

import atexit
import binascii
from contextlib import contextmanager
import cPickle
Expand Down Expand Up @@ -804,6 +805,7 @@ def __init__(self, protected_path, timeout=0, delay=0.05):
self.timeout = timeout
self.delay = delay
self._locked = False
atexit.register(self.release)

@property
def locked(self):
Expand All @@ -817,11 +819,14 @@ def acquire(self, blocking=True):
``False``.

Otherwise, check every `self.delay` seconds until it acquires
lock or exceeds `self.timeout` and raises an exception.
lock or exceeds `self.timeout` and raises an `~AcquisitionError`.

"""
start = time.time()
while True:

self._validate_lockfile()

try:
fd = os.open(self.lockfile, os.O_CREAT | os.O_EXCL | os.O_RDWR)
with os.fdopen(fd, 'w') as fd:
Expand All @@ -830,6 +835,7 @@ def acquire(self, blocking=True):
except OSError as err:
if err.errno != errno.EEXIST: # pragma: no cover
raise

if self.timeout and (time.time() - start) >= self.timeout:
raise AcquisitionError('Lock acquisition timed out.')
if not blocking:
Expand All @@ -839,10 +845,36 @@ def acquire(self, blocking=True):
self._locked = True
return True

def _validate_lockfile(self):
"""Check existence and validity of lockfile.

If the lockfile exists, but contains an invalid PID
or the PID of a non-existant process, it is removed.

"""
try:
with open(self.lockfile) as fp:
s = fp.read()
except Exception:
return

try:
pid = int(s)
except ValueError:
return self.release()

from background import _process_exists
if not _process_exists(pid):
self.release()

def release(self):
"""Release the lock by deleting `self.lockfile`."""
self._locked = False
os.unlink(self.lockfile)
try:
os.unlink(self.lockfile)
except (OSError, IOError) as err: # pragma: no cover
if err.errno != 2:
raise err

def __enter__(self):
"""Acquire lock."""
Expand Down Expand Up @@ -1942,26 +1974,30 @@ def filter(self, query, items, key=lambda x: x, ascending=False,
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 startswith
``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` : Match if ``query`` is a substring
of item search key (case-insensitive).
8. :const:`MATCH_ALLCHARS` : Matches if all characters in
``query`` appear in item search key in the same 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).
9. :const:`MATCH_ALL` : Combination of all the above.
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
Expand Down Expand Up @@ -2400,7 +2436,11 @@ def update_available(self):
:returns: ``True`` if an update is available, else ``False``

"""
update_data = self.cached_data('__workflow_update_status', max_age=0)
# 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 : {0}'.format(update_data))

if not update_data or not update_data.get('available'):
Expand Down
Loading