Skip to content

Commit 4faf08f

Browse files
committed
Update Alfred-Workflow
1 parent f5a7982 commit 4faf08f

13 files changed

+1990
-563
lines changed

README.md

+17-6
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,45 @@
11

2-
# StackOverflow Search for Alfred #
2+
StackOverflow Search for Alfred
3+
===============================
34

45
Search for answers on StackOverflow.com from [Alfred 2 & 3][alfred].
56

67
![](demo.gif "")
78

8-
## Download ##
9+
10+
Download
11+
--------
912

1013
Get StackOverflow for Alfred from [GitHub][gh-releases] or
1114
[Packal][packal-page].
1215

13-
## Usage ##
16+
17+
Usage
18+
-----
1419

1520
- `.so <query>` — Search StackOverflow.com for `<query>`.
1621
See below for syntax.
1722
- `` or ` ⌘+NUM` — Open result in default browser
1823
- `⌘+L` — Show full question title in Alfred's Large Text window
1924

20-
## Query syntax ##
25+
26+
Query syntax
27+
------------
2128

2229
By default, words in `<query>` will be search for in the title of posts. To
2330
specify a tag, prefix it with `.`, e.g. `python` will search for `python` in
2431
the post title, `.python` will search for the tag `python`.
2532

26-
## Results ##
33+
34+
Results
35+
-------
2736

2837
Answered questions will be shown first in the list of results (and have a
2938
tick on their icon).
3039

31-
## Licensing, thanks ##
40+
41+
Licensing, thanks
42+
-----------------
3243

3344
This workflow is released under the [MIT Licence][mit].
3445

StackOverflow-1.2.1.alfredworkflow

132 KB
Binary file not shown.

StackOverflow-1.2.alfredworkflow

-84.3 KB
Binary file not shown.

src/version

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.2
1+
1.2.1

src/workflow/Notify.tgz

34.7 KB
Binary file not shown.

src/workflow/__init__.py

+47-47
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,13 @@
88
# Created on 2014-02-15
99
#
1010

11-
"""
12-
A Python helper library for `Alfred 2 <http://www.alfredapp.com/>`_ Workflow
13-
authors.
14-
"""
11+
"""A helper library for `Alfred <http://www.alfredapp.com/>`_ workflows."""
1512

1613
import os
1714

18-
__title__ = 'Alfred-Workflow'
19-
__version__ = open(os.path.join(os.path.dirname(__file__), 'version')).read()
20-
__author__ = 'Dean Jackson'
21-
__licence__ = 'MIT'
22-
__copyright__ = 'Copyright 2014 Dean Jackson'
23-
24-
2515
# Workflow objects
2616
from .workflow import Workflow, manager
17+
from .workflow3 import Variables, Workflow3
2718

2819
# Exceptions
2920
from .workflow import PasswordNotFound, KeychainError
@@ -68,41 +59,50 @@
6859
MATCH_SUBSTRING,
6960
)
7061

62+
63+
__title__ = 'Alfred-Workflow'
64+
__version__ = open(os.path.join(os.path.dirname(__file__), 'version')).read()
65+
__author__ = 'Dean Jackson'
66+
__licence__ = 'MIT'
67+
__copyright__ = 'Copyright 2014 Dean Jackson'
68+
7169
__all__ = [
72-
Workflow,
73-
manager,
74-
PasswordNotFound,
75-
KeychainError,
76-
ICON_ACCOUNT,
77-
ICON_BURN,
78-
ICON_CLOCK,
79-
ICON_COLOR,
80-
ICON_COLOUR,
81-
ICON_EJECT,
82-
ICON_ERROR,
83-
ICON_FAVORITE,
84-
ICON_FAVOURITE,
85-
ICON_GROUP,
86-
ICON_HELP,
87-
ICON_HOME,
88-
ICON_INFO,
89-
ICON_NETWORK,
90-
ICON_NOTE,
91-
ICON_SETTINGS,
92-
ICON_SWIRL,
93-
ICON_SWITCH,
94-
ICON_SYNC,
95-
ICON_TRASH,
96-
ICON_USER,
97-
ICON_WARNING,
98-
ICON_WEB,
99-
MATCH_ALL,
100-
MATCH_ALLCHARS,
101-
MATCH_ATOM,
102-
MATCH_CAPITALS,
103-
MATCH_INITIALS,
104-
MATCH_INITIALS_CONTAIN,
105-
MATCH_INITIALS_STARTSWITH,
106-
MATCH_STARTSWITH,
107-
MATCH_SUBSTRING,
70+
'Variables',
71+
'Workflow',
72+
'Workflow3',
73+
'manager',
74+
'PasswordNotFound',
75+
'KeychainError',
76+
'ICON_ACCOUNT',
77+
'ICON_BURN',
78+
'ICON_CLOCK',
79+
'ICON_COLOR',
80+
'ICON_COLOUR',
81+
'ICON_EJECT',
82+
'ICON_ERROR',
83+
'ICON_FAVORITE',
84+
'ICON_FAVOURITE',
85+
'ICON_GROUP',
86+
'ICON_HELP',
87+
'ICON_HOME',
88+
'ICON_INFO',
89+
'ICON_NETWORK',
90+
'ICON_NOTE',
91+
'ICON_SETTINGS',
92+
'ICON_SWIRL',
93+
'ICON_SWITCH',
94+
'ICON_SYNC',
95+
'ICON_TRASH',
96+
'ICON_USER',
97+
'ICON_WARNING',
98+
'ICON_WEB',
99+
'MATCH_ALL',
100+
'MATCH_ALLCHARS',
101+
'MATCH_ATOM',
102+
'MATCH_CAPITALS',
103+
'MATCH_INITIALS',
104+
'MATCH_INITIALS_CONTAIN',
105+
'MATCH_INITIALS_STARTSWITH',
106+
'MATCH_STARTSWITH',
107+
'MATCH_SUBSTRING',
108108
]

src/workflow/background.py

+52-53
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
#!/usr/bin/env python
22
# encoding: utf-8
33
#
4-
# Copyright © 2014 [email protected]
4+
# Copyright (c) 2014 [email protected]
55
#
66
# MIT Licence. See http://opensource.org/licenses/MIT
77
#
88
# Created on 2014-04-06
99
#
1010

11-
"""
12-
Run background tasks
13-
"""
11+
"""Run background tasks."""
1412

1513
from __future__ import print_function, unicode_literals
1614

@@ -23,45 +21,49 @@
2321

2422
__all__ = ['is_running', 'run_in_background']
2523

26-
wf = Workflow()
27-
log = wf.logger
24+
_wf = None
25+
26+
27+
def wf():
28+
global _wf
29+
if _wf is None:
30+
_wf = Workflow()
31+
return _wf
2832

2933

3034
def _arg_cache(name):
31-
"""Return path to pickle cache file for arguments
35+
"""Return path to pickle cache file for arguments.
3236
3337
:param name: name of task
3438
:type name: ``unicode``
3539
:returns: Path to cache file
3640
:rtype: ``unicode`` filepath
3741
3842
"""
39-
40-
return wf.cachefile('{}.argcache'.format(name))
43+
return wf().cachefile('{0}.argcache'.format(name))
4144

4245

4346
def _pid_file(name):
44-
"""Return path to PID file for ``name``
47+
"""Return path to PID file for ``name``.
4548
4649
:param name: name of task
4750
:type name: ``unicode``
4851
:returns: Path to PID file for task
4952
:rtype: ``unicode`` filepath
5053
5154
"""
52-
53-
return wf.cachefile('{}.pid'.format(name))
55+
return wf().cachefile('{0}.pid'.format(name))
5456

5557

5658
def _process_exists(pid):
57-
"""Check if a process with PID ``pid`` exists
59+
"""Check if a process with PID ``pid`` exists.
5860
5961
:param pid: PID to check
6062
:type pid: ``int``
6163
:returns: ``True`` if process exists, else ``False``
6264
:rtype: ``Boolean``
63-
"""
6465
66+
"""
6567
try:
6668
os.kill(pid, 0)
6769
except OSError: # not running
@@ -70,8 +72,7 @@ def _process_exists(pid):
7072

7173

7274
def is_running(name):
73-
"""
74-
Test whether task is running under ``name``
75+
"""Test whether task is running under ``name``.
7576
7677
:param name: name of task
7778
:type name: ``unicode``
@@ -107,32 +108,31 @@ def _background(stdin='/dev/null', stdout='/dev/null',
107108
:type stderr: filepath
108109
109110
"""
111+
def _fork_and_exit_parent(errmsg):
112+
try:
113+
pid = os.fork()
114+
if pid > 0:
115+
os._exit(0)
116+
except OSError as err:
117+
wf().logger.critical('%s: (%d) %s', errmsg, err.errno,
118+
err.strerror)
119+
raise err
110120

111121
# Do first fork.
112-
try:
113-
pid = os.fork()
114-
if pid > 0:
115-
sys.exit(0) # Exit first parent.
116-
except OSError as e:
117-
log.critical("fork #1 failed: (%d) %s\n" % (e.errno, e.strerror))
118-
sys.exit(1)
122+
_fork_and_exit_parent('fork #1 failed')
123+
119124
# Decouple from parent environment.
120-
os.chdir(wf.workflowdir)
121-
os.umask(0)
125+
os.chdir(wf().workflowdir)
122126
os.setsid()
127+
123128
# Do second fork.
124-
try:
125-
pid = os.fork()
126-
if pid > 0:
127-
sys.exit(0) # Exit second parent.
128-
except OSError as e:
129-
log.critical("fork #2 failed: (%d) %s\n" % (e.errno, e.strerror))
130-
sys.exit(1)
129+
_fork_and_exit_parent('fork #2 failed')
130+
131131
# Now I am a daemon!
132132
# Redirect standard file descriptors.
133-
si = file(stdin, 'r', 0)
134-
so = file(stdout, 'a+', 0)
135-
se = file(stderr, 'a+', 0)
133+
si = open(stdin, 'r', 0)
134+
so = open(stdout, 'a+', 0)
135+
se = open(stderr, 'a+', 0)
136136
if hasattr(sys.stdin, 'fileno'):
137137
os.dup2(si.fileno(), sys.stdin.fileno())
138138
if hasattr(sys.stdout, 'fileno'):
@@ -142,8 +142,7 @@ def _background(stdin='/dev/null', stdout='/dev/null',
142142

143143

144144
def run_in_background(name, args, **kwargs):
145-
"""Pickle arguments to cache file, then call this script again via
146-
:func:`subprocess.call`.
145+
r"""Cache arguments then call this script again via :func:`subprocess.call`.
147146
148147
:param name: name of task
149148
:type name: ``unicode``
@@ -167,40 +166,39 @@ def run_in_background(name, args, **kwargs):
167166
return immediately and will not run the specified command.
168167
169168
"""
170-
171169
if is_running(name):
172-
log.info('Task `{}` is already running'.format(name))
170+
wf().logger.info('Task `{0}` is already running'.format(name))
173171
return
174172

175173
argcache = _arg_cache(name)
176174

177175
# Cache arguments
178176
with open(argcache, 'wb') as file_obj:
179177
pickle.dump({'args': args, 'kwargs': kwargs}, file_obj)
180-
log.debug('Command arguments cached to `{}`'.format(argcache))
178+
wf().logger.debug('Command arguments cached to `{0}`'.format(argcache))
181179

182180
# Call this script
183181
cmd = ['/usr/bin/python', __file__, name]
184-
log.debug('Calling {!r} ...'.format(cmd))
182+
wf().logger.debug('Calling {0!r} ...'.format(cmd))
185183
retcode = subprocess.call(cmd)
186184
if retcode: # pragma: no cover
187-
log.error('Failed to call task in background')
185+
wf().logger.error('Failed to call task in background')
188186
else:
189-
log.debug('Executing task `{}` in background...'.format(name))
187+
wf().logger.debug('Executing task `{0}` in background...'.format(name))
190188
return retcode
191189

192190

193191
def main(wf): # pragma: no cover
194-
"""
192+
"""Run command in a background process.
193+
195194
Load cached arguments, fork into background, then call
196-
:meth:`subprocess.call` with cached arguments
195+
:meth:`subprocess.call` with cached arguments.
197196
198197
"""
199-
200198
name = wf.args[0]
201199
argcache = _arg_cache(name)
202200
if not os.path.exists(argcache):
203-
log.critical('No arg cache found : {!r}'.format(argcache))
201+
wf.logger.critical('No arg cache found : {0!r}'.format(argcache))
204202
return 1
205203

206204
# Load cached arguments
@@ -221,23 +219,24 @@ def main(wf): # pragma: no cover
221219

222220
# Write PID to file
223221
with open(pidfile, 'wb') as file_obj:
224-
file_obj.write('{}'.format(os.getpid()))
222+
file_obj.write('{0}'.format(os.getpid()))
225223

226224
# Run the command
227225
try:
228-
log.debug('Task `{}` running'.format(name))
229-
log.debug('cmd : {!r}'.format(args))
226+
wf.logger.debug('Task `{0}` running'.format(name))
227+
wf.logger.debug('cmd : {0!r}'.format(args))
230228

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

233231
if retcode:
234-
log.error('Command failed with [{}] : {!r}'.format(retcode, args))
232+
wf.logger.error('Command failed with [{0}] : {1!r}'.format(
233+
retcode, args))
235234

236235
finally:
237236
if os.path.exists(pidfile):
238237
os.unlink(pidfile)
239-
log.debug('Task `{}` finished'.format(name))
238+
wf.logger.debug('Task `{0}` finished'.format(name))
240239

241240

242241
if __name__ == '__main__': # pragma: no cover
243-
wf.run(main)
242+
wf().run(main)

0 commit comments

Comments
 (0)