Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Python 3.7 #102

Merged
merged 5 commits into from
Jun 20, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 4 additions & 1 deletion .landscape.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@ pep257:
- 'D203'
# 1 blank line required after class docstring
- 'D204'

# Multi-line docstring summary should start at the first line
- 'D212'
# First line should be in imperative mood
- 'D401'

pep8:
# style checking
Expand Down
9 changes: 8 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,14 @@ matrix:
- python: 3.4
env: TOXENV=py34 TEST_QUICK=1 COVERAGE_ID=travis-ci
- python: 3.5
env: TOXENV=py35 COVERAGE_ID=travis-ci
env: TOXENV=py35 TEST_QUICK=1 COVERAGE_ID=travis-ci
- python: 3.6
env: TOXENV=py36 COVERAGE_ID=travis-ci
- python: 3.7-dev
env: TOXENV=py37 COVERAGE_ID=travis-ci
before_install:
# work around https://github.com/travis-ci/travis-ci/issues/8363
- pyenv global system 3.6
install:
- pip install tox
script:
Expand Down
2 changes: 1 addition & 1 deletion bin/display-maxcanon.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python
"""
This tool uses pexpect to test expected Canonical mode length.
A tool which uses pexpect to test expected Canonical mode length.

All systems use the value of MAX_CANON which can be found using
fpathconf(3) value PC_MAX_CANON -- with the exception of Linux
Expand Down
6 changes: 3 additions & 3 deletions bin/editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,9 @@ def readline(term, width=20):
text = text[:-1]
# https://utcc.utoronto.ca/~cks/space/blog/unix/HowUnixBackspaces
#
# "When you hit backspace, the kernel tty line discipline rubs out your previous
# character by printing (in the simple case) Ctrl-H, a space, and then another
# Ctrl-H."
# "When you hit backspace, the kernel tty line discipline rubs out
# your previous character by printing (in the simple case)
# Ctrl-H, a space, and then another Ctrl-H."
echo(u'\b \b')
return text

Expand Down
2 changes: 1 addition & 1 deletion bin/on_resize.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python
"""
This is an example application for the 'blessed' Terminal library for python.
Example application for the 'blessed' Terminal library for python.

Window size changes are caught by the 'on_resize' function using a traditional
signal handler. Meanwhile, blocking keyboard input is displayed to stdout.
Expand Down
2 changes: 1 addition & 1 deletion bin/progress_bar.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python
"""
This is an example application for the 'blessed' Terminal library for python.
Example application for the 'blessed' Terminal library for python.

This isn't a real progress bar, just a sample "animated prompt" of sorts
that demonstrates the separate move_x() and move_y() functions, made
Expand Down
4 changes: 2 additions & 2 deletions bin/worms.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python
"""
This is an example application for the 'blessed' Terminal library for python.
Example application for the 'blessed' Terminal library for python.

It is also an experiment in functional programming.
"""
Expand All @@ -25,7 +25,7 @@
import sys

def echo(text):
"""python 2 version of print(end='', flush=True)."""
"""Python 2 version of print(end='', flush=True)."""
sys.stdout.write(u'{0}'.format(text))
sys.stdout.flush()

Expand Down
22 changes: 11 additions & 11 deletions blessed/formatters.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""This sub-module provides sequence-formatting functions."""
"""Sub-module providing sequence-formatting functions."""
# standard imports
import curses

Expand Down Expand Up @@ -59,10 +59,10 @@ def __new__(cls, *args):
:arg normal: terminating sequence for this capability (optional).
:arg name: name of this terminal capability (optional).
"""
assert len(args) and len(args) < 4, args
assert args and len(args) < 4, args
new = six.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>'
new._normal = args[1] if len(args) > 1 else u''
new._name = args[2] if len(args) > 2 else u'<not specified>'
return new

def __call__(self, *args):
Expand All @@ -84,7 +84,7 @@ def __call__(self, *args):
except TypeError as err:
# If the first non-int (i.e. incorrect) arg was a string, suggest
# something intelligent:
if len(args) and isinstance(args[0], six.string_types):
if args and isinstance(args[0], six.string_types):
raise TypeError(
"A native or nonexistent capability template, %r received"
" invalid argument %r: %s. You probably misspelled a"
Expand Down Expand Up @@ -135,13 +135,13 @@ def __new__(cls, *args):
:arg normal: terminating sequence for this capability (optional).
:arg name: name of this terminal capability (optional).
"""
assert len(args) and len(args) < 4, args
assert args and len(args) < 4, args
assert isinstance(args[0], tuple), args[0]
assert callable(args[0][1]), args[0][1]
new = six.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>'
new._normal = args[1] if len(args) > 1 else u''
new._name = args[2] if len(args) > 2 else u'<not specified>'
return new

def __call__(self, *args):
Expand Down Expand Up @@ -226,7 +226,7 @@ def __new__(cls, *args):
"""
assert 1 <= len(args) <= 2, args
new = six.text_type.__new__(cls, args[0])
new._normal = len(args) > 1 and args[1] or u''
new._normal = args[1] if len(args) > 1 else u''
return new

def __call__(self, *args):
Expand All @@ -246,7 +246,7 @@ def __call__(self, *args):
expected_types=six.string_types,
))
postfix = u''
if len(self) and self._normal:
if self and self._normal:
postfix = self._normal
_refresh = self._normal + self
args = [_refresh.join(ucs_part.split(self._normal))
Expand Down Expand Up @@ -281,7 +281,7 @@ def __call__(self, *args):
the first arg, acting in place of :class:`FormattingString` without
any attributes.
"""
if len(args) == 0 or isinstance(args[0], int):
if not args or isinstance(args[0], int):
# As a NullCallableString, even when provided with a parameter,
# such as t.color(5), we must also still be callable, fe:
#
Expand Down
10 changes: 3 additions & 7 deletions blessed/keyboard.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""This sub-module provides 'keyboard awareness'."""
"""Sub-module providing 'keyboard awareness'."""

# std imports
import curses.has_key
Expand Down Expand Up @@ -52,8 +52,7 @@ def is_sequence(self):

def __repr__(self):
"""Docstring overwritten."""
return (self._name is None and
six.text_type.__repr__(self) or
return (six.text_type.__repr__(self) if self._name is None else
self._name)
__repr__.__doc__ = six.text_type.__doc__

Expand Down Expand Up @@ -246,10 +245,7 @@ class method :meth:`~.Terminal.kbhit` and similar functions.
:returns: time remaining as float. If no time is remaining,
then the integer ``0`` is returned.
"""
if timeout is not None:
if timeout == 0:
return 0
return max(0, timeout - (time.time() - stime))
return max(0, timeout - (time.time() - stime)) if timeout else timeout


def _read_until(term, pattern, timeout):
Expand Down
11 changes: 6 additions & 5 deletions blessed/sequences.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# encoding: utf-8
"""This module provides 'sequence awareness'."""
"""Module providing 'sequence awareness'."""
# std imports
import functools
import textwrap
Expand Down Expand Up @@ -129,14 +129,14 @@ def build(cls, name, capability, attribute, nparams=0,
return cls(name, pattern, attribute)

if match_grouped:
pattern = re.sub(r'(\d+)', _numeric_regex, _outp)
pattern = re.sub(r'(\d+)', lambda x: _numeric_regex, _outp)
else:
pattern = re.sub(r'\d+', _numeric_regex, _outp)
pattern = re.sub(r'\d+', lambda x: _numeric_regex, _outp)
return cls(name, pattern, attribute)


class SequenceTextWrapper(textwrap.TextWrapper):
"""This docstring overridden."""
"""Docstring overridden."""

def __init__(self, width, term, **kwargs):
"""
Expand Down Expand Up @@ -195,7 +195,8 @@ def _wrap_chunks(self, chunks):
return lines

def _handle_long_word(self, reversed_chunks, cur_line, cur_len, width):
"""Sequence-aware :meth:`textwrap.TextWrapper._handle_long_word`.
"""
Sequence-aware :meth:`textwrap.TextWrapper._handle_long_word`.

This simply ensures that word boundaries are not broken mid-sequence,
as standard python textwrap would incorrectly determine the length
Expand Down
16 changes: 9 additions & 7 deletions blessed/terminal.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# encoding: utf-8
"""This module contains :class:`Terminal`, the primary API entry point."""
"""Module containing :class:`Terminal`, the primary API entry point."""
# pylint: disable=too-many-lines
# Too many lines in module (1027/1000)
import codecs
Expand Down Expand Up @@ -75,6 +75,9 @@
)


_CUR_TERM = None # See comments at end of file


class Terminal(object):
"""
An abstraction for color, style, positioning, and input in the terminal.
Expand Down Expand Up @@ -191,9 +194,8 @@ def __init__(self, kind=None, stream=None, force_styling=False):
self._normal = None # cache normal attr, preventing recursive lookups

# The descriptor to direct terminal initialization sequences to.
self._init_descriptor = (stream_fd is None and
sys.__stdout__.fileno() or
stream_fd)
self._init_descriptor = (sys.__stdout__.fileno() if stream_fd is None
else stream_fd)
self._kind = kind or os.environ.get('TERM', 'unknown')

if self.does_styling:
Expand Down Expand Up @@ -1009,8 +1011,8 @@ def raw(self):
A context manager for :func:`tty.setraw`.

Although both :meth:`break` and :meth:`raw` modes allow each keystroke
to be read immediately after it is pressed, Raw mode disables processing
of input and output.
to be read immediately after it is pressed, Raw mode disables
processing of input and output.

In cbreak mode, special input characters such as ``^C`` or ``^S`` are
interpreted by the terminal driver and excluded from the stdin stream.
Expand Down Expand Up @@ -1177,6 +1179,7 @@ class WINSZ(collections.namedtuple('WINSZ', (
_BUF = '\x00' * struct.calcsize(_FMT)


#: _CUR_TERM = None
#: From libcurses/doc/ncurses-intro.html (ESR, Thomas Dickey, et. al)::
#:
#: "After the call to setupterm(), the global variable cur_term is set to
Expand All @@ -1196,4 +1199,3 @@ class WINSZ(collections.namedtuple('WINSZ', (
#: Therefore, the :attr:`Terminal.kind` of each :class:`Terminal` is
#: essentially a singleton. This global variable reflects that, and a warning
#: is emitted if somebody expects otherwise.
_CUR_TERM = None
3 changes: 2 additions & 1 deletion blessed/tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,8 @@ def test_termcap_repr():

given_ttype='vt220'
given_capname = 'cursor_up'
expected = [r"<Termcap cursor_up:'\\\x1b\\[A'>",
expected = [r"<Termcap cursor_up:'\x1b\\[A'>",
r"<Termcap cursor_up:'\\\x1b\\[A'>",
r"<Termcap cursor_up:u'\\\x1b\\[A'>"]

@as_subprocess
Expand Down
1 change: 1 addition & 0 deletions requirements-analysis.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
prospector[with_pyroma]
restructuredtext_lint
doc8
Pygments
3 changes: 3 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ def _get_long_description(fname):
'Programming Language :: Python :: 3.2',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Topic :: Software Development :: Libraries',
'Topic :: Software Development :: User Interfaces',
'Topic :: Terminals'
Expand Down
20 changes: 14 additions & 6 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
[tox]
envlist = about, sa, sphinx, py{26,27,34,35}
envlist = about, sa, sphinx, py{26,27,34,35,36,37}
skip_missing_interpreters = true

[testenv]
whitelist_externals = cp
setenv = PYTHONIOENCODING=UTF8
passenv = TEST_QUICK TEST_FULL
passenv = TEST_QUICK TEST_FULL TRAVIS
deps = -rrequirements-tests.txt
commands = {envbindir}/py.test {posargs:\
--strict --verbose --verbose --color=yes \
Expand All @@ -30,33 +30,41 @@ commands = coveralls

[testenv:about]
deps = -rrequirements-about.txt
basepython = python3.5
basepython = python3.6
commands = python {toxinidir}/bin/display-sighandlers.py
python {toxinidir}/bin/display-terminalinfo.py
python {toxinidir}/bin/display-fpathconf.py
python {toxinidir}/bin/display-maxcanon.py
# Temporarily disable until limits are added to MAX_CANON logic
# python {toxinidir}/bin/display-maxcanon.py

[testenv:sa]
basepython = python3.5
basepython = python3.6
deps = -rrequirements-analysis.txt
-rrequirements-about.txt
commands = python -m compileall -fq {toxinidir}/blessed
{envbindir}/prospector \
--die-on-tool-error \
--no-external-config \
{toxinidir}
{envbindir}/rst-lint README.rst
{envbindir}/doc8 --ignore-path docs/_build --ignore D000 docs

[testenv:sphinx]
whitelist_externals = echo
basepython = python3.5
basepython = python3.6
deps = -rrequirements-docs.txt
commands = {envbindir}/sphinx-build -v -W \
-d {toxinidir}/docs/_build/doctrees \
{posargs:-b html} docs \
{toxinidir}/docs/_build/html
echo "--> open docs/_build/html/index.html for review."

[testenv:py35]
# there is not much difference of py34 vs. 35 in blessed
# library; prefer testing integration against py35, and
# just do a 'quick' on py34, if exists.
setenv = TEST_QUICK=1

[testenv:py34]
# there is not much difference of py34 vs. 35 in blessed
# library; prefer testing integration against py35, and
Expand Down