Add Python 3.3 support

Support for unicode literals was reintroduced in Python 3.3 which makes
supporting both Python 2 and Python 3 much easier, so this will be the
minimum supported Python 3 version.

Closes #8.
This commit is contained in:
Kim Silkebækken 2013-01-21 20:42:57 +01:00
parent 77f66cbbc9
commit bee427eb42
15 changed files with 91 additions and 58 deletions

View File

@ -4,7 +4,7 @@ Overview
Requirements
------------
Powerline requires Python 2.7 to work.
Powerline requires Python 3.3 or Python 2.7 to work.
Powerline uses several special glyphs to get the arrow effect and some
custom symbols for developers. This requires that you either have the symbol
@ -14,13 +14,14 @@ details.
Vim plugin requirements
^^^^^^^^^^^^^^^^^^^^^^^
The vim plugin requires a vim version with Python 2.7 support compiled in.
You can check if your vim supports Python 2 by running ``vim --version
| grep +python``.
The vim plugin requires a vim version with Python support compiled in. You
can check if your vim supports Python by running ``vim --version | grep
+python``.
If your vim version doesn't have support for Python 2, you'll have to
compile it with the ``--enable-pythoninterp`` flag (this also requires the
Python headers to be installed on your system). Please consult your
If your vim version doesn't have support for Python, you'll have to compile
it with the ``--enable-python3interp`` flag (``--enable-pythoninterp`` if
you want Python 2 support instead). Note that this also requires the related
Python headers to be installed on your system. Please consult your
distribution's documentation for details on how to compile and install
packages.
@ -48,9 +49,6 @@ To install Powerline system-wide, run the following command as root::
If you don't have root access or don't want to install Powerline
system-wide, install with ``pip install --user`` instead.
.. note:: Make sure that you install the package for Python 2. For distros
like Arch Linux you'll have to run ``pip2`` instead of ``pip``.
.. note:: This project is currently unavailable on the PyPI due to a naming
conflict with an unrelated project.

View File

@ -1,11 +1,13 @@
if ! has('python')
if ! has('python') && ! has('python3')
echohl ErrorMsg
echomsg 'You need vim compiled with Python 2 support for Powerline to work. Please consult the documentation for more details.'
echomsg 'You need vim compiled with Python 3.3 or Python 2.7 support for Powerline to work. Please consult the documentation for more details.'
echohl None
finish
endif
python import sys, vim
python sys.path.append(vim.eval('expand("<sfile>:h:h:h:h:h")'))
let s:pycmd = has('python3') ? 'python3' : 'python'
exec s:pycmd ' import sys, vim'
exec s:pycmd ' sys.path.append(vim.eval(''expand("<sfile>:h:h:h:h:h")''))'
source <sfile>:h:h/powerline.vim

View File

@ -1,13 +1,17 @@
python import uuid
python from powerline.core import Powerline
python powerline = Powerline('vim')
let s:pycmd = has('python3') ? 'python3' : 'python'
if exists('*pyeval')
exec s:pycmd ' import uuid'
exec s:pycmd ' from powerline.core import Powerline'
exec s:pycmd ' powerline = Powerline("vim")'
if exists('*py3eval')
let s:pyeval = function('py3eval')
elseif exists('*pyeval')
let s:pyeval = function('pyeval')
else
python import json, vim
exec s:pycmd ' import json, vim'
function! s:pyeval(e)
python vim.command('return ' + json.dumps(eval(vim.eval('a:e'))))
exec s:pycmd ' vim.command("return " + json.dumps(eval(vim.eval("a:e"))))'
endfunction
endif

View File

@ -5,8 +5,8 @@ import json
import os
import sys
from colorscheme import Colorscheme
from matcher import Matcher
from powerline.colorscheme import Colorscheme
from powerline.matcher import Matcher
from powerline.lib import underscore_to_camelcase
@ -37,7 +37,7 @@ class Powerline(object):
'common_config': self.config,
}
local_themes = {}
for key, local_theme_name in self.config_ext.get('local_themes', {}).iteritems():
for key, local_theme_name in self.config_ext.get('local_themes', {}).items():
key = self.get_matcher(key)
local_themes[key] = {'config': self._load_theme_config(ext, local_theme_name)}
@ -74,6 +74,6 @@ class Powerline(object):
for path in self.search_paths:
config_file_path = os.path.join(path, config_file)
if os.path.isfile(config_file_path):
with open(config_file_path, 'rb') as config_file_fp:
with open(config_file_path, 'r') as config_file_fp:
return json.load(config_file_fp)
raise IOError('Config file not found in search path: {0}'.format(config_file))

View File

@ -1,5 +1,5 @@
from memoize import memoize # NOQA
from humanize_bytes import humanize_bytes # NOQA
from powerline.lib.memoize import memoize # NOQA
from powerline.lib.humanize_bytes import humanize_bytes # NOQA
def underscore_to_camelcase(string):

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
from math import log
unit_list = zip(['', 'k', 'M', 'G', 'T', 'P'], [0, 0, 1, 2, 2, 2])
unit_list = tuple(zip(['', 'k', 'M', 'G', 'T', 'P'], [0, 0, 1, 2, 2, 2]))
def humanize_bytes(num, suffix='B', binary_prefix=False):

View File

@ -1,6 +1,9 @@
# -*- coding: utf-8 -*-
import cPickle as pickle
try:
import cPickle as pickle
except ImportError:
import pickle
import functools
import os
import tempfile

View File

@ -93,7 +93,7 @@ except ImportError:
p = Popen(cmd, shell=False, stdout=PIPE, stderr=PIPE, cwd=cwd)
p.stderr.close()
for line in p.stdout:
yield line[:-1]
yield line[:-1].decode('utf-8')
class Repository(object):
__slots__ = ('directory',)
@ -107,10 +107,10 @@ except ImportError:
def status(self, path=None):
if path:
try:
return self._gitcmd('status', '--porcelain', '--', path).next()[:2]
return next(self._gitcmd('status', '--porcelain', '--', path))[:2]
except StopIteration:
try:
self._gitcmd('ls-files', '--ignored', '--exclude-standard', '--others', '--', path).next()
next(self._gitcmd('ls-files', '--ignored', '--exclude-standard', '--others', '--', path))
return '!!'
except StopIteration:
return None

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
from colorscheme import Colorscheme
from theme import Theme
from powerline.colorscheme import Colorscheme
from powerline.theme import Theme
class Renderer(object):
@ -20,7 +20,7 @@ class Renderer(object):
self.local_themes[matcher] = theme
def get_theme(self):
for matcher in self.local_themes.iterkeys():
for matcher in self.local_themes.keys():
if matcher():
match = self.local_themes[matcher]
if 'config' in match:

View File

@ -18,6 +18,31 @@ weather_conditions_codes = {
}
def _urllib_read(url):
try:
import urllib.error
import urllib.request
try:
return urllib.request.urlopen(url).read().decode('utf-8')
except urllib.error.HTTPError:
return
except ImportError:
import urllib2
try:
return urllib2.urlopen(url).read()
except urllib2.HTTPError:
return
def _urllib_urlencode(string):
try:
import urllib.parse
return urllib.parse.urlencode(string)
except ImportError:
import urllib
return urllib.urlencode(string)
def hostname():
import socket
if not os.environ.get('SSH_CLIENT'):
@ -44,7 +69,10 @@ def branch():
def cwd(dir_shorten_len=None, dir_limit_depth=None):
import re
cwd = os.getcwdu()
try:
cwd = os.getcwdu()
except AttributeError:
cwd = os.getcwd()
home = os.environ.get('HOME')
if home:
cwd = re.sub('^' + re.escape(home), '~', cwd, 1)
@ -65,11 +93,7 @@ def date(format='%Y-%m-%d'):
@memoize(600, persistent=True)
def external_ip(query_url='http://ipv4.icanhazip.com/'):
import urllib2
try:
return urllib2.urlopen(query_url).read().strip()
except urllib2.HTTPError:
return
return _urllib_read(query_url).strip()
def uptime(format='{days:02d}d {hours:02d}h {minutes:02d}m'):
@ -92,12 +116,10 @@ def uptime(format='{days:02d}d {hours:02d}h {minutes:02d}m'):
@memoize(1800, persistent=True)
def weather(unit='c', location_query=None):
import json
import urllib
import urllib2
if not location_query:
try:
location = json.loads(urllib2.urlopen('http://freegeoip.net/json/' + external_ip()).read())
location = json.loads(_urllib_read('http://freegeoip.net/json/' + external_ip()))
location_query = ','.join([location['city'], location['region_name'], location['country_name']])
except ValueError:
return None
@ -107,8 +129,8 @@ def weather(unit='c', location_query=None):
'select * from we where location="{0}" and unit="{1}"'.format(location_query, unit),
'format': 'json'
}
url = 'http://query.yahooapis.com/v1/public/yql?' + urllib.urlencode(query_data)
response = json.loads(urllib2.urlopen(url).read())
url = 'http://query.yahooapis.com/v1/public/yql?' + _urllib_urlencode(query_data)
response = json.loads(_urllib_read(url))
condition = response['query']['results']['weather']['rss']['channel']['item']['condition']
condition_code = int(condition['code'])
icon = u''

View File

@ -39,8 +39,8 @@ vim_modes = {
}
mode_translations = {
chr(ord('V')-0x40): '^V',
chr(ord('S')-0x40): '^S',
chr(ord('V') - 0x40): '^V',
chr(ord('S') - 0x40): '^S',
}
@ -53,7 +53,7 @@ def mode(override=None):
mode = mode({ 'n': 'NORM' })
'''
mode = vim_funcs['mode']()
mode = vim_funcs['mode']().decode('utf-8')
mode = mode_translations.get(mode, mode)
if not override:
return vim_modes[mode]
@ -80,7 +80,7 @@ def readonly_indicator(text=u''):
def file_directory():
'''Return file directory (head component of the file path).'''
file_directory = vim_funcs['expand']('%:~:.:h')
file_directory = vim_funcs['expand']('%:~:.:h').decode('utf-8')
return file_directory + os.sep if file_directory else None

View File

@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
from collections import defaultdict
import copy
from collections import defaultdict
from segment import Segment
from .segment import Segment
class Theme(object):
def __init__(self, ext, colorscheme, theme_config, common_config):
@ -42,7 +42,11 @@ class Theme(object):
pass
else:
continue
segment['contents'] = unicode(segment['before'] + unicode(segment['contents']) + segment['after'])\
try:
contents = unicode(segment['contents'])
except NameError:
contents = str(segment['contents'])
segment['contents'] = (segment['before'] + contents + segment['after'])\
.ljust(segment['ljust'])\
.rjust(segment['rjust'])
# We need to yield a copy of the segment, or else mode-dependent

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''Powerline prompt script.'''
import argparse
@ -22,4 +22,4 @@ if __name__ == '__main__':
segments = pl.renderer.get_theme().get_segments()
if args.side != 'all':
segments = [s for s in segments if s['side'] == args.side]
print(pl.renderer.render(None, segments=segments).encode('utf-8'))
print(pl.renderer.render(None, segments=segments))

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''Powerline tmux statusline.'''
import argparse
@ -9,7 +9,7 @@ except ImportError:
import os
import sys
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from powerline.core import Powerline
from powerline.core import Powerline # NOQA
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('side', nargs='?', default='all', choices=('all', 'left', 'right'))
@ -21,4 +21,4 @@ if __name__ == '__main__':
segments = pl.renderer.get_theme().get_segments()
if args.side != 'all':
segments = [s for s in segments if s['side'] == args.side]
print(pl.renderer.render('n', segments=segments).encode('utf-8'))
print(pl.renderer.render(None, segments=segments))

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os