Skip to content

Commit

Permalink
Merge pull request #21 from jquast/remove-2to3-converstion
Browse files Browse the repository at this point in the history
Remove the need to use to 2to3 conversion utility
  • Loading branch information
jquast committed Sep 1, 2014
2 parents 1c81bfa + 6b483e1 commit f47ce00
Show file tree
Hide file tree
Showing 12 changed files with 82 additions and 77 deletions.
5 changes: 4 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -697,14 +697,17 @@ Version History
* enhancement: new context manager ``keypad()``, which enables
keypad application keys such as the diagonal keys on the numpad.
* bugfix: translate keypad application keys correctly.
* enhancement: no longer depend on the '2to3' tool for python 3 support.
* enhancement: allow ``civis`` and ``cnorm`` (*hide_cursor*, *normal_hide*)
to work with terminal-type *ansi* by emulating support by proxy.

1.8
* enhancement: export keyboard-read function as public method ``getch()``,
so that it may be overridden by custom terminal implementers.
* enhancement: allow ``inkey()`` and ``kbhit()`` to return early when
interrupted by signal by passing argument ``_intr_continue=False``.
* enhancement: allow ``hpa`` and ``vpa`` (*move_x*, *move_y*) to work on
tmux(1) or screen(1) by forcibly emulating their support by a proxy.
tmux(1) or screen(1) by emulating support by proxy.
* enhancement: ``setup.py develop`` ensures virtualenv and installs tox,
and ``setup.py test`` calls tox. Requires pythons defined by tox.ini.
* enhancement: add ``rstrip()`` and ``lstrip()``, strips both sequences
Expand Down
2 changes: 1 addition & 1 deletion blessed/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@
'support due to http://bugs.python.org/issue10570.')


from terminal import Terminal
from .terminal import Terminal

__all__ = ['Terminal']
23 changes: 15 additions & 8 deletions blessed/formatters.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"This sub-module provides formatting functions."
import curses
import sys

_derivatives = ('on', 'bright', 'on_bright',)

Expand All @@ -15,8 +16,14 @@
#: All valid compoundable names.
COMPOUNDABLES = (COLORS | _compoundables)

if sys.version_info[0] == 3:
text_type = str
basestring = str
else:
text_type = unicode # noqa

class ParameterizingString(unicode):

class ParameterizingString(text_type):
"""A Unicode string which can be called as a parameterizing termcap.
For example::
Expand All @@ -35,7 +42,7 @@ def __new__(cls, *args):
:arg name: name of this terminal capability.
"""
assert len(args) and len(args) < 4, args
new = unicode.__new__(cls, args[0])
new = text_type.__new__(cls, args[0])
new._normal = len(args) > 1 and args[1] or u''
new._name = len(args) > 2 and args[2] or u'<not specified>'
return new
Expand Down Expand Up @@ -74,7 +81,7 @@ def __call__(self, *args):
return NullCallableString()


class ParameterizingProxyString(unicode):
class ParameterizingProxyString(text_type):
"""A Unicode string which can be called to proxy missing termcap entries.
For example::
Expand Down Expand Up @@ -102,7 +109,7 @@ def __new__(cls, *args):
assert len(args) and len(args) < 4, args
assert type(args[0]) is tuple, args[0]
assert callable(args[0][1]), args[0][1]
new = unicode.__new__(cls, args[0][0])
new = text_type.__new__(cls, args[0][0])
new._fmt_args = args[0][1]
new._normal = len(args) > 1 and args[1] or u''
new._name = len(args) > 2 and args[2] or u'<not specified>'
Expand Down Expand Up @@ -135,7 +142,7 @@ def get_proxy_string(term, attr):
return None


class FormattingString(unicode):
class FormattingString(text_type):
"""A Unicode string which can be called using ``text``,
returning a new string, ``attr`` + ``text`` + ``normal``::
Expand All @@ -150,7 +157,7 @@ def __new__(cls, *args):
:arg normal: terminating sequence for this attribute.
"""
assert 1 <= len(args) <= 2, args
new = unicode.__new__(cls, args[0])
new = text_type.__new__(cls, args[0])
new._normal = len(args) > 1 and args[1] or u''
return new

Expand All @@ -165,12 +172,12 @@ def __call__(self, text):
return text


class NullCallableString(unicode):
class NullCallableString(text_type):
"""A dummy callable Unicode to stand in for ``FormattingString`` and
``ParameterizingString`` for terminals that cannot perform styling.
"""
def __new__(cls):
new = unicode.__new__(cls, u'')
new = text_type.__new__(cls, u'')
return new

def __call__(self, *args):
Expand Down
24 changes: 16 additions & 8 deletions blessed/keyboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@

__all__ = ['Keystroke', 'get_keyboard_codes', 'get_keyboard_sequences']

import curses
import curses.has_key
import collections
import curses
import sys

if hasattr(collections, 'OrderedDict'):
OrderedDict = collections.OrderedDict
else:
Expand Down Expand Up @@ -50,8 +52,14 @@
_lastval += 1
setattr(curses, 'KEY_{0}'.format(key), _lastval)

if sys.version_info[0] == 3:
text_type = str
unichr = chr
else:
text_type = unicode # noqa


class Keystroke(unicode):
class Keystroke(text_type):
"""A unicode-derived class for describing keyboard input returned by
the ``inkey()`` method of ``Terminal``, which may, at times, be a
multibyte sequence, providing properties ``is_sequence`` as ``True``
Expand All @@ -60,7 +68,7 @@ class Keystroke(unicode):
such as ``KEY_LEFT``.
"""
def __new__(cls, ucs='', code=None, name=None):
new = unicode.__new__(cls, ucs)
new = text_type.__new__(cls, ucs)
new._name = name
new._code = code
return new
Expand All @@ -71,8 +79,8 @@ def is_sequence(self):
return self._code is not None

def __repr__(self):
return self._name is None and unicode.__repr__(self) or self._name
__repr__.__doc__ = unicode.__doc__
return self._name is None and text_type.__repr__(self) or self._name
__repr__.__doc__ = text_type.__doc__

@property
def name(self):
Expand Down Expand Up @@ -152,7 +160,7 @@ def get_keyboard_sequences(term):
(seq.decode('latin1'), val)
for (seq, val) in (
(curses.tigetstr(cap), val)
for (val, cap) in capability_names.iteritems()
for (val, cap) in capability_names.items()
) if seq
) if term.does_styling else ())

Expand All @@ -164,7 +172,7 @@ def get_keyboard_sequences(term):
# over simple sequences such as ('\x1b', KEY_EXIT).
return OrderedDict((
(seq, sequence_map[seq]) for seq in sorted(
sequence_map, key=len, reverse=True)))
sequence_map.keys(), key=len, reverse=True)))


def resolve_sequence(text, mapper, codes):
Expand All @@ -176,7 +184,7 @@ def resolve_sequence(text, mapper, codes):
their integer value (260), and ``codes`` is a dict of integer values (260)
paired by their mnemonic name, 'KEY_LEFT'.
"""
for sequence, code in mapper.iteritems():
for sequence, code in mapper.items():
if text.startswith(sequence):
return Keystroke(ucs=sequence, code=code, name=codes[code])
return Keystroke(ucs=text and text[0] or u'')
Expand Down
14 changes: 10 additions & 4 deletions blessed/sequences.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import textwrap
import warnings
import math
import sys
import re

# 3rd-party
Expand All @@ -20,6 +21,11 @@
_BINTERM_UNSUPPORTED_MSG = ('sequence-awareness for terminals emitting '
'binary-packed capabilities are not supported.')

if sys.version_info[0] == 3:
text_type = str
else:
text_type = unicode # noqa


def _merge_sequences(inp):
"""Merge a list of input sequence patterns for use in a regular expression.
Expand Down Expand Up @@ -221,7 +227,7 @@ def get_wontmove_sequence_patterns(term):
# ( not *exactly* legal, being extra forgiving. )
bna(cap='sgr', nparams=_num) for _num in range(1, 10)
# reset_{1,2,3}string: Reset string
] + map(re.escape, (term.r1, term.r2, term.r3,)))
] + list(map(re.escape, (term.r1, term.r2, term.r3,))))


def init_sequence_patterns(term):
Expand Down Expand Up @@ -366,7 +372,7 @@ def _wrap_chunks(self, chunks):
SequenceTextWrapper.__doc__ = textwrap.TextWrapper.__doc__


class Sequence(unicode):
class Sequence(text_type):
"""
This unicode-derived class understands the effect of escape sequences
of printable length, allowing a properly implemented .rjust(), .ljust(),
Expand All @@ -379,7 +385,7 @@ def __new__(cls, sequence_text, term):
:arg sequence_text: A string containing sequences.
:arg term: Terminal instance this string was created with.
"""
new = unicode.__new__(cls, sequence_text)
new = text_type.__new__(cls, sequence_text)
new._term = term
return new

Expand Down Expand Up @@ -518,7 +524,7 @@ def padd(self):
"""
outp = u''
nxt = 0
for idx in range(0, unicode.__len__(self)):
for idx in range(0, text_type.__len__(self)):
width = horizontal_distance(self[idx:], self._term)
if width != 0:
nxt = idx + measure_length(self[idx:], self._term)
Expand Down
6 changes: 3 additions & 3 deletions blessed/terminal.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,20 +44,20 @@ class IOUnsupportedOperation(Exception):
InterruptedError = select.error

# local imports
from formatters import (
from .formatters import (
ParameterizingString,
NullCallableString,
resolve_capability,
resolve_attribute,
)

from sequences import (
from .sequences import (
init_sequence_patterns,
SequenceTextWrapper,
Sequence,
)

from keyboard import (
from .keyboard import (
get_keyboard_sequences,
get_keyboard_codes,
resolve_sequence,
Expand Down
14 changes: 11 additions & 3 deletions blessed/tests/accessories.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
"""Accessories for automated py.test runner."""
# std
from __future__ import with_statement
import contextlib
import functools
Expand All @@ -11,10 +12,17 @@
import pty
import os

# local
from blessed import Terminal

# 3rd
import pytest

if sys.version_info[0] == 3:
text_type = str
else:
text_type = unicode # noqa

TestTerminal = functools.partial(Terminal, kind='xterm-256color')
SEND_SEMAPHORE = SEMAPHORE = b'SEMAPHORE\n'
RECV_SEMAPHORE = b'SEMAPHORE\r\n'
Expand Down Expand Up @@ -78,7 +86,7 @@ def __call__(self, *args, **kwargs):
cov.save()
os._exit(0)

exc_output = unicode()
exc_output = text_type()
decoder = codecs.getincrementaldecoder(self.encoding)()
while True:
try:
Expand Down Expand Up @@ -119,7 +127,7 @@ def read_until_semaphore(fd, semaphore=RECV_SEMAPHORE,
# process will read xyz\\r\\n -- this is how pseudo terminals
# behave; a virtual terminal requires both carriage return and
# line feed, it is only for convenience that \\n does both.
outp = unicode()
outp = text_type()
decoder = codecs.getincrementaldecoder(encoding)()
semaphore = semaphore.decode('ascii')
while not outp.startswith(semaphore):
Expand All @@ -139,7 +147,7 @@ def read_until_semaphore(fd, semaphore=RECV_SEMAPHORE,
def read_until_eof(fd, encoding='utf8'):
"""Read file descriptor ``fd`` until EOF. Return decoded string."""
decoder = codecs.getincrementaldecoder(encoding)()
outp = unicode()
outp = text_type()
while True:
try:
_exc = os.read(fd, 100)
Expand Down
5 changes: 4 additions & 1 deletion blessed/tests/test_core.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
# -*- coding: utf-8 -*-
"Core blessed Terminal() tests."

# std
try:
from StringIO import StringIO
except ImportError:
from io import StringIO

import collections
import warnings
import platform
Expand All @@ -13,13 +14,15 @@
import imp
import os

# local
from accessories import (
as_subprocess,
TestTerminal,
unicode_cap,
all_terms
)

# 3rd party
import mock
import pytest

Expand Down
Loading

0 comments on commit f47ce00

Please sign in to comment.