Skip to content

Commit

Permalink
Add Bitcoin
Browse files Browse the repository at this point in the history
Update Alfred-Workflow
Rebuild and bump version
  • Loading branch information
deanishe committed Jul 15, 2015
1 parent 433b29e commit 2e2e5cb
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 21 deletions.
Binary file not shown.
18 changes: 15 additions & 3 deletions extra/Currency Lists.paw
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<databaseInfo>
<version>134481920</version>
<UUID>3609AD2E-3B86-45CC-AB5E-D556BEA75886</UUID>
<nextObjectID>112</nextObjectID>
<nextObjectID>114</nextObjectID>
<metadata>
<plist version="1.0">
<dict>
Expand Down Expand Up @@ -99,14 +99,14 @@
<attribute name="order" type="int64">0</attribute>
<attribute name="name" type="string">Default Environments</attribute>
<relationship name="environments" type="0/0" destination="LMENVIRONMENT" idrefs="z105"></relationship>
<relationship name="variables" type="0/0" destination="LMENVIRONMENTVARIABLE"></relationship>
<relationship name="variables" type="0/0" destination="LMENVIRONMENTVARIABLE" idrefs="z113"></relationship>
</object>
<object type="LMENVIRONMENT" id="z105">
<attribute name="uuid" type="string">4C70E7BC-6C0C-40F6-8D55-E7CA028E7428</attribute>
<attribute name="order" type="int64">0</attribute>
<attribute name="name" type="string">Default</attribute>
<relationship name="domain" type="0/1" destination="LMENVIRONMENTDOMAIN" idrefs="z104"></relationship>
<relationship name="variablesvalues" type="0/0" destination="LMENVIRONMENTVARIABLEVALUE"></relationship>
<relationship name="variablesvalues" type="0/0" destination="LMENVIRONMENTVARIABLEVALUE" idrefs="z114"></relationship>
</object>
<object type="LMKEYVALUE" id="z106">
<attribute name="value" type="string"></attribute>
Expand Down Expand Up @@ -168,4 +168,16 @@
<relationship name="groupforurlparameters" type="0/1" destination="LMREQUESTGROUP"></relationship>
<relationship name="request" type="0/1" destination="LMREQUEST" idrefs="z111"></relationship>
</object>
<object type="LMENVIRONMENTVARIABLE" id="z113">
<attribute name="uuid" type="string">3B0BE379-D5E5-46CC-A243-B30415931308</attribute>
<attribute name="order" type="int64">0</attribute>
<attribute name="name" type="string"></attribute>
<relationship name="domain" type="0/1" destination="LMENVIRONMENTDOMAIN" idrefs="z104"></relationship>
<relationship name="values" type="0/0" destination="LMENVIRONMENTVARIABLEVALUE" idrefs="z114"></relationship>
</object>
<object type="LMENVIRONMENTVARIABLEVALUE" id="z114">
<attribute name="value" type="string"></attribute>
<relationship name="environment" type="1/1" destination="LMENVIRONMENT" idrefs="z105"></relationship>
<relationship name="variable" type="1/1" destination="LMENVIRONMENTVARIABLE" idrefs="z113"></relationship>
</object>
</database>
1 change: 1 addition & 0 deletions icon.png
1 change: 1 addition & 0 deletions src/currencies.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"BOB": "Bolivia Boliviano",
"BRL": "Brazil Real",
"BSD": "Bahamas Dollar",
"BTC": "Bitcoin",
"BTN": "Bhutan Ngultrum",
"BWP": "Botswana Pula",
"BYR": "Belarus Ruble",
Expand Down
2 changes: 1 addition & 1 deletion src/version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.1
2.2
2 changes: 1 addition & 1 deletion src/workflow/version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.11.0
1.12
15 changes: 14 additions & 1 deletion src/workflow/web.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,11 @@
import unicodedata
import urllib
import urllib2
import urlparse
import zlib

import sys


USER_AGENT = u'Alfred-Workflow/1.11 (http://www.deanishe.net)'

Expand Down Expand Up @@ -522,7 +525,17 @@ def request(method, url, params=None, data=None, headers=None, cookies=None,
url = url.encode('utf-8')

if params: # GET args (POST args are handled in encode_multipart_formdata)
url = url + '?' + urllib.urlencode(str_dict(params))

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)
Expand Down
128 changes: 113 additions & 15 deletions src/workflow/workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"""

from __future__ import print_function, unicode_literals
from contextlib import contextmanager

import binascii
import os
Expand All @@ -32,6 +33,8 @@
import time
import logging
import logging.handlers
import signal

try:
import xml.etree.cElementTree as ET
except ImportError: # pragma: no cover
Expand Down Expand Up @@ -787,6 +790,89 @@ def elem(self):
return root


@contextmanager
def atomic_writer(file_path, mode):
"""Atomic file writer.
:param file_path: path of file to write to.
:type file_path: ``unicode``
:param mode: sames as for `func:open`
:type mode: string
.. 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.
"""

temp_suffix = '.aw.temp'
temp_file_path = file_path + temp_suffix
with open(temp_file_path, mode) as file_obj:
try:
yield file_obj
os.rename(temp_file_path, file_path)
finally:
try:
os.remove(temp_file_path)
except (OSError, IOError):
pass


class uninterruptible(object):
"""Decorator that postpones SIGTERM until wrapped function is complete.
.. versionadded:: 1.12
Since 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.
.. important::
This decorator is NOT thread-safe.
"""

def __init__(self, func, class_name=''):
self.func = 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):
# 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):
return self.__class__(self.func.__get__(obj, klass),
klass.__name__)


class Settings(dict):
"""A dictionary that saves itself when changed.
Expand Down Expand Up @@ -838,7 +924,7 @@ def save(self):
data = {}
for key, value in self.items():
data[key] = value
with open(self._filepath, 'wb') as file_obj:
with atomic_writer(self._filepath, 'wb') as file_obj:
json.dump(data, file_obj, sort_keys=True, indent=2,
encoding='utf-8')

Expand Down Expand Up @@ -1503,9 +1589,9 @@ def stored_data(self, name):

if serializer is None:
raise ValueError(
'Unknown serializer `{0}`. Register a corresponding serializer '
'with `manager.register()` to load this data.'.format(
serializer_name))
'Unknown serializer `{0}`. Register a corresponding '
'serializer with `manager.register()` '
'to load this data.'.format(serializer_name))

self.logger.debug('Data `{0}` stored in `{1}` format'.format(
name, serializer_name))
Expand Down Expand Up @@ -1534,6 +1620,8 @@ def store_data(self, name, data, serializer=None):
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.
Expand All @@ -1544,6 +1632,15 @@ def store_data(self, name, data, serializer=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 : {0}'.format(path))

serializer_name = serializer or self.data_serializer

# In order for `stored_data()` to be able to load data stored with
Expand All @@ -1567,19 +1664,20 @@ def store_data(self, name, data, serializer=None):
'`manager.register()` first.'.format(serializer_name))

if data is None: # Delete cached data
for path in (metadata_path, data_path):
if os.path.exists(path):
os.unlink(path)
self.logger.debug('Deleted data file : {0}'.format(path))

delete_paths((metadata_path, data_path))
return

# Save file extension
with open(metadata_path, 'wb') as file_obj:
file_obj.write(serializer_name)
# 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 open(data_path, 'wb') as file_obj:
serializer.dump(data, file_obj)
with atomic_writer(data_path, 'wb') as file_obj:
serializer.dump(data, file_obj)

_store()

self.logger.debug('Stored data saved at : {0}'.format(data_path))

Expand Down Expand Up @@ -1640,7 +1738,7 @@ def cache_data(self, name, data):
self.logger.debug('Deleted cache file : %s', cache_path)
return

with open(cache_path, 'wb') as file_obj:
with atomic_writer(cache_path, 'wb') as file_obj:
serializer.dump(data, file_obj)

self.logger.debug('Cached data saved at : %s', cache_path)
Expand Down

0 comments on commit 2e2e5cb

Please sign in to comment.