diff --git a/VPN-Manager-3.2.alfredworkflow b/VPN-Manager-3.3.alfredworkflow similarity index 74% rename from VPN-Manager-3.2.alfredworkflow rename to VPN-Manager-3.3.alfredworkflow index e38a065..d6d297d 100644 Binary files a/VPN-Manager-3.2.alfredworkflow and b/VPN-Manager-3.3.alfredworkflow differ diff --git a/src/docopt.py b/src/docopt.py index 7b927e2..11b564b 100644 --- a/src/docopt.py +++ b/src/docopt.py @@ -478,7 +478,7 @@ def formal_usage(printable_usage): def extras(help, version, options, doc): if help and any((o.name in ('-h', '--help')) and o.value for o in options): - print(doc.strip("\n")) + print((doc.strip("\n"))) sys.exit() if version and any(o.name == '--version' and o.value for o in options): print(version) @@ -487,7 +487,7 @@ def extras(help, version, options, doc): class Dict(dict): def __repr__(self): - return '{%s}' % ',\n '.join('%r: %r' % i for i in sorted(self.items())) + return '{%s}' % ',\n '.join('%r: %r' % i for i in sorted(self.items(), key=lambda x: str(x))) def docopt(doc, argv=None, help=True, version=None, options_first=False): diff --git a/src/info.plist b/src/info.plist index 3eceadb..549c6ad 100644 --- a/src/info.plist +++ b/src/info.plist @@ -125,7 +125,7 @@ escaping 0 script - /usr/bin/python vpn.py $action "$1" + /usr/bin/python3 vpn.py $action "$1" scriptargtype 1 scriptfile @@ -166,7 +166,7 @@ runningsubtext Loading VPN information… script - /usr/bin/python vpn.py list "$1" + /usr/bin/python3 vpn.py list "$1" scriptargtype 1 scriptfile @@ -213,7 +213,7 @@ runningsubtext Loading apps… script - /usr/bin/python vpn.py conf "$1" + /usr/bin/python3 vpn.py conf "$1" scriptargtype 1 scriptfile @@ -337,7 +337,7 @@ echo "query=$query" >&2 app=$( echo "$query" | cut -d: -f2 ) -/usr/bin/python vpn.py app "$app" +/usr/bin/python3 vpn.py app "$app" echo "$app" scriptargtype @@ -477,7 +477,7 @@ or Tunnelblick app from https://tunnelblick.net/ VPN_APP version - 3.2 + 3.3 webaddress https://github.com/deanishe/alfred-vpn-manager diff --git a/src/vpn.py b/src/vpn.py index 4a83840..5aab027 100755 --- a/src/vpn.py +++ b/src/vpn.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3 # encoding: utf-8 # # Copyright (c) 2015 deanishe@deanishe.net @@ -23,7 +23,7 @@ -h, --help Show this message and exit. """ -from __future__ import print_function, absolute_import + import abc from collections import namedtuple @@ -92,11 +92,9 @@ def timed(name=None): # 88 88 88 # dP dP dP -class VPNApp(object): +class VPNApp(object, metaclass=abc.ABCMeta): """Base class for application classes.""" - __metaclass__ = abc.ABCMeta - def __init__(self): """Create new initialised `VPNApp`.""" self._info = False @@ -142,7 +140,7 @@ def connect(self, name): """Connect to named VPN.""" connections = self.filter_connections(name=name, active=False) for c in connections: - log.info(u'connecting "%s" ...', c.name) + log.info('connecting "%s" ...', c.name) cmd = self.program + ['connect', c.name] run_command(cmd) @@ -151,7 +149,7 @@ def disconnect(self, name): """Disconnect from named VPN.""" connections = self.filter_connections(name=name, active=True) for c in connections: - log.info(u'disconnecting "%s" ...', c.name) + log.info('disconnecting "%s" ...', c.name) cmd = self.program + ['disconnect', c.name] run_command(cmd) @@ -204,7 +202,7 @@ def _fetch_connections(self): data = json.loads(run_command(cmd)) - for t in data.items(): + for t in list(data.items()): connections.append(VPN(*t)) return connections @@ -291,7 +289,7 @@ def show_update(): """Add an 'update available!' item.""" if wf.update_available: wf.add_item('Workflow Update Available!', - u'↩ or ⇥ to install update', + '↩ or ⇥ to install update', autocomplete='workflow:update', valid=False, icon=ICON_UPDATE_AVAILABLE) @@ -314,7 +312,7 @@ def do_config(query): items.append(dict( title=title, - subtitle=u'↩ or ⇥ to install update', + subtitle='↩ or ⇥ to install update', autocomplete='workflow:update', valid=False, icon=icon, @@ -325,8 +323,8 @@ def do_config(query): for app in get_all_apps(): if app.selected and app.installed: items.append(dict( - title=u'{} (active)'.format(app.name), - subtitle=u'{} is the active application'.format(app.name), + title='{} (active)'.format(app.name), + subtitle='{} is the active application'.format(app.name), icon=app.info.path, icontype='fileicon', valid=False, @@ -334,8 +332,8 @@ def do_config(query): else: if app.installed: items.append(dict( - title=u'{}'.format(app.name), - subtitle=u'↩ to use {}'.format(app.name), + title='{}'.format(app.name), + subtitle='↩ to use {}'.format(app.name), icon=app.info.path, icontype='fileicon', arg='app:' + app.name, @@ -343,8 +341,8 @@ def do_config(query): )) else: items.append(dict( - title=u'{} (not installed)'.format(app.name), - subtitle=u'↩ to get {}'.format(app.name), + title='{} (not installed)'.format(app.name), + subtitle='↩ to get {}'.format(app.name), icon=ICON_WEB, arg=app.download_url, valid=True, @@ -404,7 +402,7 @@ def do_list(query): try: app = get_app() except NotInstalled as err: - wf.add_item(err.message, + wf.add_item(str(err), 'Use "vpnconf" to change the application', valid=False, icon=ICON_WARNING) @@ -473,7 +471,7 @@ def do_list(query): it = wf.add_item( con.name, - u'↩ to connect', + '↩ to connect', uid=uid, arg=con.name, valid=True, @@ -512,7 +510,7 @@ def main(wf): """Run workflow.""" args = docopt.docopt(__doc__, wf.args, version=wf.version) - log.debug('args : %r', args) + log.debug('args : !r', args) if args['list']: return do_list(args.get('')) diff --git a/src/workflow/__init__.py b/src/workflow/__init__.py index 17636a4..87a7fde 100644 --- a/src/workflow/__init__.py +++ b/src/workflow/__init__.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # encoding: utf-8 # # Copyright (c) 2014 Dean Jackson diff --git a/src/workflow/background.py b/src/workflow/background.py index ba5c52a..d4643f9 100644 --- a/src/workflow/background.py +++ b/src/workflow/background.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # encoding: utf-8 # # Copyright (c) 2014 deanishe@deanishe.net @@ -17,7 +17,7 @@ and examples. """ -from __future__ import print_function, unicode_literals + import signal import sys @@ -25,7 +25,7 @@ import subprocess import pickle -from workflow import Workflow +from .workflow import Workflow __all__ = ['is_running', 'run_in_background'] @@ -96,7 +96,7 @@ def _job_pid(name): if not os.path.exists(pidfile): return - with open(pidfile, 'rb') as fp: + with open(pidfile, 'r') as fp: pid = int(fp.read()) if _process_exists(pid): @@ -143,7 +143,7 @@ def _fork_and_exit_parent(errmsg, wait=False, write=False): if pid > 0: if write: # write PID of child process to `pidfile` tmp = pidfile + '.tmp' - with open(tmp, 'wb') as fp: + with open(tmp, 'w') as fp: fp.write(str(pid)) os.rename(tmp, pidfile) if wait: # wait for child process to exit @@ -233,7 +233,7 @@ def run_in_background(name, args, **kwargs): _log().debug('[%s] command cached: %s', name, argcache) # Call this script - cmd = ['/usr/bin/python', __file__, name] + cmd = ['/usr/bin/python3', __file__, name] _log().debug('[%s] passing job to background runner: %r', name, cmd) retcode = subprocess.call(cmd) diff --git a/src/workflow/notify.py b/src/workflow/notify.py index a4b7f40..e0e9066 100644 --- a/src/workflow/notify.py +++ b/src/workflow/notify.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # encoding: utf-8 # # Copyright (c) 2015 deanishe@deanishe.net @@ -23,7 +23,7 @@ icon and then calls the application to post notifications. """ -from __future__ import print_function, unicode_literals + import os import plistlib @@ -34,7 +34,7 @@ import tempfile import uuid -import workflow +from . import workflow _wf = None diff --git a/src/workflow/update.py b/src/workflow/update.py index 6affc94..bd4c55f 100644 --- a/src/workflow/update.py +++ b/src/workflow/update.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # encoding: utf-8 # # Copyright (c) 2014 Fabio Niephaus , @@ -21,7 +21,7 @@ """ -from __future__ import print_function, unicode_literals + from collections import defaultdict from functools import total_ordering @@ -31,8 +31,8 @@ import re import subprocess -import workflow -import web +from . import workflow +from . import web # __all__ = [] @@ -119,7 +119,7 @@ def from_releases(cls, js): release['prerelease'])) valid = True - for ext, n in dupes.items(): + for ext, n in list(dupes.items()): if n > 1: wf().logger.debug('ignored release "%s": multiple assets ' 'with extension "%s"', tag, ext) @@ -143,7 +143,7 @@ def __init__(self, url, filename, version, prerelease=False): pre-release. Defaults to False. """ - if isinstance(version, basestring): + if isinstance(version, str): version = Version(version) self.url = url @@ -172,7 +172,7 @@ def __str__(self): 'version={dl.version!r}, ' 'prerelease={dl.prerelease!r})'.format(dl=self)) - return u.encode('utf-8') + return u def __repr__(self): """Code-like representation of `Download`.""" diff --git a/src/workflow/util.py b/src/workflow/util.py index 27209d8..f8ea4ed 100644 --- a/src/workflow/util.py +++ b/src/workflow/util.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # encoding: utf-8 # # Copyright (c) 2017 Dean Jackson @@ -10,7 +10,7 @@ """A selection of helper functions useful for building workflows.""" -from __future__ import print_function, absolute_import + import atexit from collections import namedtuple @@ -86,9 +86,9 @@ def jxa_app_name(): """ if os.getenv('alfred_version', '').startswith('3'): # Alfred 3 - return u'Alfred 3' + return 'Alfred 3' # Alfred 4+ - return u'com.runningwithcrayons.Alfred' + return 'com.runningwithcrayons.Alfred' def unicodify(s, encoding='utf-8', norm=None): @@ -108,8 +108,8 @@ def unicodify(s, encoding='utf-8', norm=None): unicode: Decoded, optionally normalised, Unicode string. """ - if not isinstance(s, unicode): - s = unicode(s, encoding) + if not isinstance(s, str): + s = str(s, encoding) if norm: from unicodedata import normalize @@ -136,7 +136,7 @@ def utf8ify(s): if isinstance(s, str): return s - if isinstance(s, unicode): + if isinstance(s, str): return s.encode('utf-8') return str(s) @@ -161,7 +161,7 @@ def applescriptify(s): unicode: Escaped string """ - return s.replace(u'"', u'" & quote & "') + return s.replace('"', '" & quote & "') def run_command(cmd, **kwargs): @@ -181,7 +181,7 @@ def run_command(cmd, **kwargs): """ cmd = [utf8ify(s) for s in cmd] - return subprocess.check_output(cmd, **kwargs) + return subprocess.check_output(cmd, **kwargs).decode('utf8', errors='ignore') def run_applescript(script, *args, **kwargs): @@ -383,7 +383,7 @@ class LockFile(object): >>> path = '/path/to/file' >>> with LockFile(path): - >>> with open(path, 'wb') as fp: + >>> with open(path, 'w') as fp: >>> fp.write(data) Args: diff --git a/src/workflow/web.py b/src/workflow/web.py index 0781911..1e7b63b 100644 --- a/src/workflow/web.py +++ b/src/workflow/web.py @@ -18,13 +18,13 @@ import socket import string import unicodedata -import urllib -import urllib2 -import urlparse +import urllib.request, urllib.parse, urllib.error +import urllib.request, urllib.error, urllib.parse +import urllib.parse import zlib -USER_AGENT = u'Alfred-Workflow/1.36 (+http://www.deanishe.net/alfred-workflow)' +USER_AGENT = 'Alfred-Workflow/1.36 (+http://www.deanishe.net/alfred-workflow)' # Valid characters for multipart form data boundaries BOUNDARY_CHARS = string.digits + string.ascii_letters @@ -87,16 +87,16 @@ def str_dict(dic): 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') + for k, v in list(dic.items()): + if isinstance(k, bytes): + k = k.decode('utf-8') + if isinstance(v, bytes): + v = v.decode('utf-8') dic2[k] = v return dic2 -class NoRedirectHandler(urllib2.HTTPRedirectHandler): +class NoRedirectHandler(urllib.request.HTTPRedirectHandler): """Prevent redirections.""" def redirect_request(self, *args): @@ -120,7 +120,7 @@ class CaseInsensitiveDictionary(dict): def __init__(self, initval=None): """Create new case-insensitive dictionary.""" if isinstance(initval, dict): - for key, value in initval.iteritems(): + for key, value in initval.items(): self.__setitem__(key, value) elif isinstance(initval, list): @@ -147,34 +147,34 @@ def get(self, key, default=None): def update(self, other): """Update values from other ``dict``.""" - for k, v in other.items(): + 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.itervalues(self)] + return [(v['key'], v['val']) for v in super(CaseInsensitiveDictionary, self).values()] def keys(self): """Return original keys.""" - return [v['key'] for v in dict.itervalues(self)] + return [v['key'] for v in super(CaseInsensitiveDictionary, self).values()] def values(self): """Return all values.""" - return [v['val'] for v in dict.itervalues(self)] + return [v['val'] for v in super(CaseInsensitiveDictionary, self).values()] def iteritems(self): """Iterate over ``(key, value)`` pairs.""" - for v in dict.itervalues(self): + for v in super(CaseInsensitiveDictionary, self).values(): yield v['key'], v['val'] def iterkeys(self): """Iterate over original keys.""" - for v in dict.itervalues(self): + for v in super(CaseInsensitiveDictionary, self).values(): yield v['key'] def itervalues(self): """Interate over values.""" - for v in dict.itervalues(self): + for v in super(CaseInsensitiveDictionary, self).values(): yield v['val'] @@ -220,8 +220,8 @@ def __init__(self, request, stream=False): # Execute query try: - self.raw = urllib2.urlopen(request) - except urllib2.HTTPError as err: + self.raw = urllib.request.urlopen(request) + except urllib.error.HTTPError as err: self.error = err try: self.url = err.geturl() @@ -240,9 +240,8 @@ def __init__(self, request, stream=False): # 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.mimetype = headers.get_content_type() + for key in list(headers.keys()): self.headers[key.lower()] = headers.get(key) # Is content gzipped? @@ -327,7 +326,7 @@ def text(self): """ if self.encoding: - return unicodedata.normalize('NFC', unicode(self.content, + return unicodedata.normalize('NFC', str(self.content, self.encoding)) return self.content @@ -400,7 +399,7 @@ def save_to_path(self, filepath): self.stream = True - with open(filepath, 'wb') as fileobj: + with open(filepath, 'w') as fileobj: for data in self.iter_content(): fileobj.write(data) @@ -519,14 +518,14 @@ def request(method, url, params=None, data=None, headers=None, cookies=None, if auth is not None: # Add authorisation handler username, password = auth - password_manager = urllib2.HTTPPasswordMgrWithDefaultRealm() + password_manager = urllib.request.HTTPPasswordMgrWithDefaultRealm() password_manager.add_password(None, url, username, password) - auth_manager = urllib2.HTTPBasicAuthHandler(password_manager) + auth_manager = urllib.request.HTTPBasicAuthHandler(password_manager) openers.append(auth_manager) # Install our custom chain of openers - opener = urllib2.build_opener(*openers) - urllib2.install_opener(opener) + opener = urllib.request.build_opener(*openers) + urllib.request.install_opener(opener) if not headers: headers = CaseInsensitiveDictionary() @@ -554,28 +553,25 @@ def request(method, url, params=None, data=None, headers=None, cookies=None, new_headers, data = encode_multipart_formdata(data, files) headers.update(new_headers) elif data and isinstance(data, dict): - data = urllib.urlencode(str_dict(data)) + 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 = urlparse.urlsplit(url) + scheme, netloc, path, query, fragment = urllib.parse.urlsplit(url) if query: # Combine query string and `params` - url_params = urlparse.parse_qs(query) + url_params = urllib.parse.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)) + query = urllib.parse.urlencode(str_dict(params), doseq=True) + url = urllib.parse.urlunsplit((scheme, netloc, path, query, fragment)) - req = urllib2.Request(url, data, headers) + req = urllib.request.Request(url, data, headers) return Response(req, stream) @@ -644,30 +640,30 @@ def get_content_type(filename): 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') + for (name, value) in list(fields.items()): + if isinstance(name, bytes): + name = name.decode('utf-8') + if isinstance(value, bytes): + value = value.decode('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'] + for name, d in list(files.items()): + filename = d['filename'] + content = d['content'] + if 'mimetype' in d: + mimetype = d['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') + if isinstance(name, bytes): + name = name.decode('utf-8') + if isinstance(filename, bytes): + filename = filename.decode('utf-8') + if isinstance(mimetype, bytes): + mimetype = mimetype.decode('utf-8') output.append('--' + boundary) output.append('Content-Disposition: form-data; ' 'name="%s"; filename="%s"' % (name, filename)) diff --git a/src/workflow/workflow.py b/src/workflow/workflow.py index 2a057b0..629256f 100644 --- a/src/workflow/workflow.py +++ b/src/workflow/workflow.py @@ -19,10 +19,10 @@ """ -from __future__ import print_function, unicode_literals + import binascii -import cPickle +import pickle from copy import deepcopy import json import logging @@ -44,8 +44,8 @@ import xml.etree.ElementTree as ET # imported to maintain API -from util import AcquisitionError # noqa: F401 -from util import ( +from .util import AcquisitionError # noqa: F401 +from .util import ( atomic_writer, LockFile, uninterruptible, @@ -619,7 +619,7 @@ def dump(cls, obj, file_obj): :type file_obj: ``file`` object """ - return json.dump(obj, file_obj, indent=2, encoding='utf-8') + return json.dump(obj, file_obj, indent=2) class CPickleSerializer(object): @@ -644,7 +644,7 @@ def load(cls, file_obj): :rtype: object """ - return cPickle.load(file_obj) + return pickle.load(file_obj) @classmethod def dump(cls, obj, file_obj): @@ -658,7 +658,7 @@ def dump(cls, obj, file_obj): :type file_obj: ``file`` object """ - return cPickle.dump(obj, file_obj, protocol=-1) + return pickle.dump(obj, file_obj, protocol=-1) class PickleSerializer(object): @@ -826,7 +826,7 @@ def __init__(self, filepath, defaults=None): if os.path.exists(self._filepath): self._load() elif defaults: - for key, val in defaults.items(): + for key, val in list(defaults.items()): self[key] = val self.save() # save default settings @@ -834,7 +834,7 @@ 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: + with open(self._filepath, 'r') as fp: data.update(json.load(fp)) self._original = deepcopy(data) @@ -858,9 +858,8 @@ def save(self): 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') + with atomic_writer(self._filepath, 'w') as fp: + json.dump(data, fp, sort_keys=True, indent=2) # dict methods def __setitem__(self, key, value): @@ -996,7 +995,7 @@ def __init__(self, default_settings=None, update_settings=None, @property def alfred_version(self): """Alfred version as :class:`~workflow.update.Version` object.""" - from update import Version + from .update import Version return Version(self.alfred_env.get('version')) @property @@ -1100,7 +1099,7 @@ def bundleid(self): if self.alfred_env.get('workflow_bundleid'): self._bundleid = self.alfred_env.get('workflow_bundleid') else: - self._bundleid = unicode(self.info['bundleid'], 'utf-8') + self._bundleid = str(self.info['bundleid'], 'utf-8') return self._bundleid @@ -1163,7 +1162,7 @@ def version(self): filepath = self.workflowfile('version') if os.path.exists(filepath): - with open(filepath, 'rb') as fileobj: + with open(filepath, 'r') as fileobj: version = fileobj.read() # info.plist @@ -1171,7 +1170,7 @@ def version(self): version = self.info.get('version') if version: - from update import Version + from .update import Version version = Version(version) self._version = version @@ -1299,7 +1298,7 @@ def workflowdir(self): # 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.abspath(os.getcwd()), os.path.dirname(os.path.abspath(os.path.dirname(__file__)))] # climb the directory tree until we find `info.plist` @@ -1571,7 +1570,7 @@ def stored_data(self, name): self.logger.debug('no data stored for `%s`', name) return None - with open(metadata_path, 'rb') as file_obj: + with open(metadata_path, 'r') as file_obj: serializer_name = file_obj.read().strip() serializer = manager.serializer(serializer_name) @@ -1594,7 +1593,7 @@ def stored_data(self, name): return None - with open(data_path, 'rb') as file_obj: + with open(data_path, 'r') as file_obj: data = serializer.load(file_obj) self.logger.debug('stored data loaded: %s', data_path) @@ -1658,10 +1657,10 @@ def delete_paths(paths): @uninterruptible def _store(): # Save file extension - with atomic_writer(metadata_path, 'wb') as file_obj: + with atomic_writer(metadata_path, 'w') as file_obj: file_obj.write(serializer_name) - with atomic_writer(data_path, 'wb') as file_obj: + with atomic_writer(data_path, 'w') as file_obj: serializer.dump(data, file_obj) _store() @@ -2083,7 +2082,7 @@ def run(self, func, text_errors=False): if not sys.stdout.isatty(): # Show error in Alfred if text_errors: - print(unicode(err).encode('utf-8'), end='') + print(str(err).encode('utf-8'), end='') else: self._items = [] if self._name: @@ -2093,7 +2092,7 @@ def run(self, func, text_errors=False): else: # pragma: no cover name = os.path.dirname(__file__) self.add_item("Error in workflow '%s'" % name, - unicode(err), + str(err), icon=ICON_ERROR) self.send_feedback() return 1 @@ -2217,7 +2216,7 @@ def last_version_run(self): version = self.settings.get('__workflow_last_version') if version: - from update import Version + from .update import Version version = Version(version) self._last_version_run = version @@ -2245,8 +2244,8 @@ def set_last_version(self, version=None): version = self.version - if isinstance(version, basestring): - from update import Version + if isinstance(version, str): + from .update import Version version = Version(version) self.settings['__workflow_last_version'] = str(version) @@ -2324,13 +2323,13 @@ def check_update(self, force=False): # version = self._update_settings['version'] version = str(self.version) - from background import run_in_background + 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') + 'update.py') - cmd = ['/usr/bin/python', update_script, 'check', repo, version] + cmd = ['/usr/bin/python3', update_script, 'check', repo, version] if self.prereleases: cmd.append('--prereleases') @@ -2354,7 +2353,7 @@ def start_update(self): installed, else ``False`` """ - import update + from . import update repo = self._update_settings['github_slug'] # version = self._update_settings['version'] @@ -2363,13 +2362,13 @@ def start_update(self): if not update.check_update(repo, version, self.prereleases): return False - from background import run_in_background + 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') + 'update.py') - cmd = ['/usr/bin/python', update_script, 'install', repo, version] + cmd = ['/usr/bin/python3', update_script, 'install', repo, version] if self.prereleases: cmd.append('--prereleases') @@ -2456,7 +2455,7 @@ def get_password(self, account, service=None): h = groups.get('hex') password = groups.get('pw') if h: - password = unicode(binascii.unhexlify(h), 'utf-8') + password = str(binascii.unhexlify(h), 'utf-8') self.logger.debug('got password : %s:%s', service, account) @@ -2698,8 +2697,8 @@ def decode(self, text, encoding=None, normalization=None): """ encoding = encoding or self._input_encoding normalization = normalization or self._normalizsation - if not isinstance(text, unicode): - text = unicode(text, encoding) + if not isinstance(text, str): + text = str(text, encoding) return unicodedata.normalize(normalization, text) def fold_to_ascii(self, text): @@ -2718,7 +2717,7 @@ def fold_to_ascii(self, text): if isascii(text): return text text = ''.join([ASCII_REPLACEMENTS.get(c, c) for c in text]) - return unicode(unicodedata.normalize('NFKD', + return str(unicodedata.normalize('NFKD', text).encode('ascii', 'ignore')) def dumbify_punctuation(self, text): diff --git a/src/workflow/workflow3.py b/src/workflow/workflow3.py index b92c4be..f1b56dd 100644 --- a/src/workflow/workflow3.py +++ b/src/workflow/workflow3.py @@ -23,7 +23,7 @@ """ -from __future__ import print_function, unicode_literals, absolute_import + import json import os @@ -72,7 +72,7 @@ def obj(self): o = {} if self: d2 = {} - for k, v in self.items(): + for k, v in list(self.items()): d2[k] = v o['variables'] = d2 @@ -95,7 +95,7 @@ def __unicode__(self): if self.arg: return self.arg else: - return u'' + return '' return json.dumps(self.obj) @@ -106,7 +106,7 @@ def __str__(self): str: UTF-8 encoded ``alfredworkflow`` JSON object """ - return unicode(self).encode('utf-8') + return str(self) class Modifier(object): @@ -438,7 +438,7 @@ def _modifiers(self): """ if self.modifiers: mods = {} - for k, mod in self.modifiers.items(): + for k, mod in list(self.modifiers.items()): mods[k] = mod.obj return mods @@ -689,7 +689,7 @@ def obj(self): o['rerun'] = self.rerun return o - def warn_empty(self, title, subtitle=u'', icon=None): + def warn_empty(self, title, subtitle='', icon=None): """Add a warning to feedback if there are no items. .. versionadded:: 1.31