38 Commits

Author SHA1 Message Date
kennethreitz 9d3693d644 Merge pull request #173 from EdwardBetts/spelling
correct spelling mistake
2017-09-02 00:38:47 -04:00
Edward Betts ee695135a7 correct spelling mistake 2017-09-01 20:47:08 +01:00
kennethreitz e4ba837bad Merge pull request #151 from thusoy/custom-chars
Progress bar: Don't ignore custom bar characters
2017-08-29 01:57:19 -04:00
kennethreitz 3b77ef3b43 Merge pull request #171 from hvnsweeting/master
Fix an example
2017-08-29 01:56:47 -04:00
kennethreitz 2698af12dd Merge pull request #167 from sebix/fix-testsuite
Add test suite to setup.py
2017-08-29 01:56:21 -04:00
kennethreitz 195ab0de4d Update README.rst 2017-08-29 01:55:31 -04:00
kennethreitz b16b2248cd Merge pull request #93 from futoase/support-travis
Created: Added .travis.yml
2017-08-29 01:54:58 -04:00
kennethreitz dc8fbfd355 Merge pull request #148 from wkentaro/maxwidth-with-context-manager
Support clint.textui.max_width as context manager
2017-08-29 01:53:51 -04:00
kennethreitz 8f42b40900 Merge pull request #142 from j00bar/password-input
Support password inputs in textui.prompt.query
2017-08-29 01:53:15 -04:00
kennethreitz 96013432d9 Merge pull request #154 from robtandy/update_readme
Change "Application" to "Interface" in Readme.
2017-08-29 01:52:53 -04:00
kennethreitz 84ce2ed9b1 Merge pull request #161 from waldyrious/patch-1
add license title
2017-08-29 01:52:24 -04:00
kennethreitz 8c3cbe984b Merge pull request #168 from graingert/patch-1
Support universal wheels
2017-07-07 20:12:03 -04:00
Hung Nguyen Viet d0fe6df171 Pep8 fix 2017-02-03 21:03:18 +07:00
Hung Nguyen Viet 7865d7a375 Add clint to import paths 2017-02-03 21:03:01 +07:00
kennethreitz 0931dbff9f Merge pull request #169 from jwilk/spelling
Fix typo
2017-01-27 00:46:45 -05:00
Jakub Wilk 8dc046b9c7 Fix typo 2017-01-26 16:31:56 +01:00
Thomas Grainger 39322ea11f Support universal wheels 2016-10-31 14:19:01 +00:00
kennethreitz a190f64e3c Merge pull request #153 from Scorpil/fix_unicode_error_python2
Fix unicode error python2
2016-10-26 13:29:40 -04:00
Sebastian Wagner a7a28da410 Add test suite to setup.py
Allows running the tests with `python setup.py test`

Signed-off-by: Sebastian Wagner <sebix@sebix.at>
2016-10-13 22:31:28 +02:00
Waldir Pimenta a1203ff9d9 add license title
It's not strictly required, but it's useful metadata, and part of the recommended license template text (see http://choosealicense.com/licenses/isc/ and https://opensource.org/licenses/isc-license)
2016-06-30 14:39:44 +01:00
rob tandy 16e50a62e1 Clant -> Clint 2016-01-05 19:01:28 +00:00
Andrew Savchyn a173f763d0 Fix unicode conversion for Python 2 2015-12-14 00:40:27 +01:00
Andrew Savchyn e101c56eed Test for unicode error in magic methods (Python 2) 2015-12-14 00:26:36 +01:00
Tarjei Husøy 52ff92d7d5 Progress bar: Don't ignore custom bar characters
Closes #131.
2015-09-12 23:54:07 +02:00
Kentaro Wada 34ec848479 Support clint.textui.max_width as context manager 2015-09-11 04:28:12 +09:00
Jason Piper 2bd5aef5bc v0.5.1 2015-08-26 00:11:27 +08:00
Jason Piper a47ed4f711 Merge pull request #147 from wkentaro/fix-max-width-for-colored-text
Fix wrong line width calculation in max_width for colored text
2015-08-26 00:06:55 +08:00
Kentaro Wada d0a5237afe Update AUTHORS 2015-08-26 00:58:06 +09:00
Kentaro Wada d6cb52f8b3 Fix wrong line width calculation in max_width for colored text 2015-08-26 00:58:01 +09:00
Joshua "jag" Ginsberg a09b1efa76 Support password inputs in textui.prompt.query 2015-04-17 11:23:10 -04:00
Keiji Matsuzaki 85d5f52549 Merge pull request #1 from ashleyh/master
fixed tests for py3.x and added coveralls.io support
2013-11-20 04:31:15 -08:00
Ashley Hewson 7be8140d91 Update README.rst 2013-11-19 20:32:24 +00:00
aph fb96edf52f badges! 2013-11-19 20:30:21 +00:00
Ashley Hewson 439de410c0 formatting 2013-11-19 20:21:51 +00:00
aph 5a88ee3a52 let's try coveralls 2013-11-19 20:00:06 +00:00
aph 3077b0f53e fix for py3.x 2013-11-19 19:47:58 +00:00
Ashley Hewson 5e7a191957 Update .travis.yml 2013-11-19 16:54:53 +00:00
futoase 6aedd380cf Created: Added .travis.yml 2013-10-07 12:51:52 +09:00
18 changed files with 167 additions and 36 deletions
+13
View File
@@ -0,0 +1,13 @@
language: python
python:
- 2.6
- 2.7
- 3.2
- 3.3
- pypy
install:
- pip install pytest args coveralls pytest-cov
script:
- py.test --cov clint
after_success:
- coveralls
+1
View File
@@ -31,3 +31,4 @@ Patches and Suggestions
- Eric Anderson - Eric Anderson
- Joshua Richardson - Joshua Richardson
- Brandon Liu <thenovices> - Brandon Liu <thenovices>
- Kentaro Wada <www.kentaro.wada@gmail.com>
+5 -1
View File
@@ -1,6 +1,10 @@
History History
------- -------
0.5.1
+++++
* Fix line width calculation in max_width when using coloured text (thanks to @wkentaro)
0.5.0 0.5.0
+++++ +++++
* Added option prompt * Added option prompt
@@ -73,7 +77,7 @@ History
0.2.3 0.2.3
+++++ +++++
* Only init colors if they are used (iPython compatability) * Only init colors if they are used (iPython compatibility)
* New progress module * New progress module
* Various bugfixes * Various bugfixes
+3 -1
View File
@@ -1,3 +1,5 @@
ISC License
Copyright (c) 2011, Kenneth Reitz <me@kennethreitz.com> Copyright (c) 2011, Kenneth Reitz <me@kennethreitz.com>
Permission to use, copy, modify, and/or distribute this software for any Permission to use, copy, modify, and/or distribute this software for any
@@ -10,4 +12,4 @@ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+3 -2
View File
@@ -1,4 +1,4 @@
Clint: Python Command-line Application Tools Clint: Python Command-line Interface Tools
============================================ ============================================
**Clint** is a module filled with a set of awesome tools for developing **Clint** is a module filled with a set of awesome tools for developing
@@ -28,7 +28,8 @@ Run the various executables in examples_ to get a good feel for what Clint offer
You'll never want to not use it. You'll never want to not use it.
.. image:: https://travis-ci.org/kennethreitz/clint.png?branch=master
:target: https://travis-ci.org/kennethreitz/clint
Current Features: Current Features:
----------------- -----------------
+2 -2
View File
@@ -26,8 +26,8 @@ from .pipes import piped_in
__title__ = 'clint' __title__ = 'clint'
__version__ = '0.5.0' __version__ = '0.5.1'
__build__ = 0x000500 __build__ = 0x000501
__author__ = 'Kenneth Reitz' __author__ = 'Kenneth Reitz'
__license__ = 'ISC' __license__ = 'ISC'
__copyright__ = 'Copyright 2012 Kenneth Reitz' __copyright__ = 'Copyright 2012 Kenneth Reitz'
+6 -5
View File
@@ -18,6 +18,7 @@ import sys
PY3 = sys.version_info[0] >= 3 PY3 = sys.version_info[0] >= 3
from ..packages import colorama from ..packages import colorama
from ..utils import basestring
__all__ = ( __all__ = (
'red', 'green', 'yellow', 'blue', 'red', 'green', 'yellow', 'blue',
@@ -42,7 +43,10 @@ class ColoredString(object):
"""Enhanced string for __len__ operations on Colored output.""" """Enhanced string for __len__ operations on Colored output."""
def __init__(self, color, s, always_color=False, bold=False): def __init__(self, color, s, always_color=False, bold=False):
super(ColoredString, self).__init__() super(ColoredString, self).__init__()
self.s = s if not PY3 and isinstance(s, unicode):
self.s = s.encode('utf-8')
else:
self.s = s
self.color = color self.color = color
self.always_color = always_color self.always_color = always_color
self.bold = bold self.bold = bold
@@ -93,10 +97,7 @@ class ColoredString(object):
__str__ = __unicode__ __str__ = __unicode__
else: else:
def __str__(self): def __str__(self):
value = self.color_str return self.color_str
if isinstance(value, bytes):
return value
return value.encode('utf8')
def __iter__(self): def __iter__(self):
return iter(self.color_str) return iter(self.color_str)
+6 -1
View File
@@ -15,7 +15,7 @@ import sys
from contextlib import contextmanager from contextlib import contextmanager
from .formatters import max_width, min_width from .formatters import max_width, min_width, _get_max_width_context
from .cols import columns from .cols import columns
from ..utils import tsplit from ..utils import tsplit
@@ -53,6 +53,11 @@ def _indent(indent=0, quote='', indent_char=' '):
def puts(s='', newline=True, stream=STDOUT): def puts(s='', newline=True, stream=STDOUT):
"""Prints given string to stdout.""" """Prints given string to stdout."""
max_width_ctx = _get_max_width_context()
if max_width_ctx:
cols, separator = max_width_ctx[-1]
s = max_width(s, cols, separator)
if newline: if newline:
s = tsplit(s, NEWLINES) s = tsplit(s, NEWLINES)
s = map(str, s) s = map(str, s)
+71 -9
View File
@@ -9,12 +9,14 @@ Core TextUI functionality for text formatting.
""" """
from __future__ import absolute_import from __future__ import absolute_import
from contextlib import contextmanager
from .colored import ColoredString, clean from .colored import ColoredString, clean
from ..utils import tsplit, schunk from ..utils import tsplit, schunk
NEWLINES = ('\n', '\r', '\r\n') NEWLINES = ('\n', '\r', '\r\n')
MAX_WIDTHS = []
def min_width(string, cols, padding=' '): def min_width(string, cols, padding=' '):
@@ -33,17 +35,72 @@ def min_width(string, cols, padding=' '):
return '\n'.join(stack) return '\n'.join(stack)
def max_width(string, cols, separator='\n'): def _get_max_width_context():
"""Returns a freshly formatted """ return MAX_WIDTHS
@contextmanager
def _max_width_context():
"""Max width context manager."""
try:
yield
finally:
MAX_WIDTHS.pop()
def max_width(*args, **kwargs):
"""Returns formatted text or context manager for textui:puts.
>>> from clint.textui import puts, max_width
>>> max_width('123 5678', 8)
'123 5678'
>>> max_width('123 5678', 7)
'123 \n5678'
>>> with max_width(7):
... puts('123 5678')
'123 \n5678'
"""
args = list(args)
if not args:
args.append(kwargs.get('string'))
args.append(kwargs.get('cols'))
args.append(kwargs.get('separator'))
elif len(args) == 1:
args.append(kwargs.get('cols'))
args.append(kwargs.get('separator'))
elif len(args) == 2:
args.append(kwargs.get('separator'))
string, cols, separator = args
if separator is None:
separator = '\n' # default value
if cols is None:
# cols should be specified vitally
# because string can be specified at textui:puts function
string, cols = cols, string
if string is None:
MAX_WIDTHS.append((cols, separator))
return _max_width_context()
else:
return _max_width_formatter(string, cols, separator)
def _max_width_formatter(string, cols, separator='\n'):
"""Returns a freshly formatted
:param string: string to be formatted
:type string: basestring or clint.textui.colored.ColoredString
:param cols: max width the text to be formatted
:type cols: int
:param separator: separator to break rows
:type separator: basestring
"""
is_color = isinstance(string, ColoredString) is_color = isinstance(string, ColoredString)
if is_color: if is_color:
offset = 10
string_copy = string._new('') string_copy = string._new('')
else: string = string.s
offset = 0
stack = tsplit(string, NEWLINES) stack = tsplit(string, NEWLINES)
for i, substring in enumerate(stack): for i, substring in enumerate(stack):
@@ -56,31 +113,36 @@ def max_width(string, cols, separator='\n'):
_row_i = 0 _row_i = 0
for word in row: for word in row:
if (len(_row[_row_i]) + len(word)) < (cols + offset): if (len(_row[_row_i]) + len(word)) <= cols:
_row[_row_i] += word _row[_row_i] += word
_row[_row_i] += ' ' _row[_row_i] += ' '
elif len(word) > (cols - offset): elif len(word) > cols:
# ensure empty row # ensure empty row
if len(_row[_row_i]): if len(_row[_row_i]):
_row[_row_i] = _row[_row_i].rstrip()
_row.append('') _row.append('')
_row_i += 1 _row_i += 1
chunks = schunk(word, (cols + offset)) chunks = schunk(word, cols)
for i, chunk in enumerate(chunks): for i, chunk in enumerate(chunks):
if not (i + 1) == len(chunks): if not (i + 1) == len(chunks):
_row[_row_i] += chunk _row[_row_i] += chunk
_row[_row_i] = _row[_row_i].rstrip()
_row.append('') _row.append('')
_row_i += 1 _row_i += 1
else: else:
_row[_row_i] += chunk _row[_row_i] += chunk
_row[_row_i] += ' ' _row[_row_i] += ' '
else: else:
_row[_row_i] = _row[_row_i].rstrip()
_row.append('') _row.append('')
_row_i += 1 _row_i += 1
_row[_row_i] += word _row[_row_i] += word
_row[_row_i] += ' ' _row[_row_i] += ' '
else:
_row[_row_i] = _row[_row_i].rstrip()
_row = map(str, _row) _row = map(str, _row)
_stack.append(separator.join(_row)) _stack.append(separator.join(_row))
+2 -2
View File
@@ -109,8 +109,8 @@ def bar(it, label='', width=32, hide=None, empty_char=BAR_EMPTY_CHAR,
count = len(it) if expected_size is None else expected_size count = len(it) if expected_size is None else expected_size
with Bar(label=label, width=width, hide=hide, empty_char=BAR_EMPTY_CHAR, with Bar(label=label, width=width, hide=hide, empty_char=empty_char,
filled_char=BAR_FILLED_CHAR, expected_size=count, every=every) \ filled_char=filled_char, expected_size=count, every=every) \
as bar: as bar:
for i, item in enumerate(it): for i, item in enumerate(it):
yield item yield item
+4 -2
View File
@@ -11,6 +11,7 @@ Module for simple interactive prompts handling
from __future__ import absolute_import, print_function from __future__ import absolute_import, print_function
from re import match, I from re import match, I
import getpass
from .core import puts from .core import puts
from .colored import yellow from .colored import yellow
@@ -59,7 +60,7 @@ def yn(prompt, default='y', batch=False):
return True if default == 'n' else False return True if default == 'n' else False
def query(prompt, default='', validators=None, batch=False): def query(prompt, default='', validators=None, batch=False, mask_input=False):
# Set the nonempty validator as default # Set the nonempty validator as default
if validators is None: if validators is None:
validators = [RegexValidator(r'.+')] validators = [RegexValidator(r'.+')]
@@ -76,7 +77,8 @@ def query(prompt, default='', validators=None, batch=False):
# If batch option is True then auto reply # If batch option is True then auto reply
# with default input # with default input
if not batch: if not batch:
user_input = raw_input(prompt).strip() or default user_input_fn = getpass.getpass if mask_input else raw_input
user_input = user_input_fn(prompt).strip() or default
else: else:
print(prompt) print(prompt)
user_input = '' user_input = ''
+1 -1
View File
@@ -17,7 +17,7 @@ from os import makedirs
from glob import glob from glob import glob
try: try:
basestring basestring = basestring
except NameError: except NameError:
basestring = str basestring = str
+4 -2
View File
@@ -1,6 +1,8 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import print_function
import sys import sys
import os import os
@@ -17,6 +19,6 @@ with indent(4, quote='>>>'):
puts(colored.red('Files detected: ') + str(args.files)) puts(colored.red('Files detected: ') + str(args.files))
puts(colored.red('NOT Files detected: ') + str(args.not_files)) puts(colored.red('NOT Files detected: ') + str(args.not_files))
puts(colored.red('Grouped Arguments: ') + str(dict(args.grouped))) puts(colored.red('Grouped Arguments: ') + str(dict(args.grouped)))
print print()
+6 -1
View File
@@ -1,6 +1,11 @@
#! /usr/bin/env python #! /usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import sys
import os
sys.path.insert(0, os.path.abspath('..'))
from clint.arguments import Args from clint.arguments import Args
from clint.textui import puts, colored from clint.textui import puts, colored
@@ -8,6 +13,6 @@ all_args = Args().grouped
for item in all_args: for item in all_args:
if item is not '_': if item is not '_':
puts(colored.red("key:%s"%item)) puts(colored.red("key:%s" % item))
print(all_args[item].all) print(all_args[item].all)
+2
View File
@@ -0,0 +1,2 @@
[bdist_wheel]
universal=1
+1
View File
@@ -54,4 +54,5 @@ setup(
'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.4',
'Topic :: Terminals :: Terminal Emulators/X Terminals', 'Topic :: Terminals :: Terminal Emulators/X Terminals',
], ],
test_suite='test_clint',
) )
+36 -6
View File
@@ -18,25 +18,25 @@ class ClintTestCase(unittest.TestCase):
pass pass
class ColoredStringTestCase(unittest.TestCase): class ColoredStringTestCase(unittest.TestCase):
def setUp(self): def setUp(self):
from clint.textui.colored import ColoredString from clint.textui.colored import ColoredString
def tearDown(self): def tearDown(self):
pass pass
def test_split(self): def test_split(self):
from clint.textui.colored import ColoredString from clint.textui.colored import ColoredString
new_str = ColoredString('red', "hello world") new_str = ColoredString('red', "hello world")
output = new_str.split() output = new_str.split()
assert output[0].s == "hello" assert output[0].s == "hello"
def test_find(self): def test_find(self):
from clint.textui.colored import ColoredString from clint.textui.colored import ColoredString
new_str = ColoredString('blue', "hello world") new_str = ColoredString('blue', "hello world")
output = new_str.find('h') output = new_str.find('h')
self.assertEqual(output, 0) self.assertEqual(output, 0)
def test_replace(self): def test_replace(self):
from clint.textui.colored import ColoredString from clint.textui.colored import ColoredString
new_str = ColoredString('green', "hello world") new_str = ColoredString('green', "hello world")
@@ -49,7 +49,6 @@ class ColoredStringTestCase(unittest.TestCase):
new_str = ColoredString('RED', '\xe4') new_str = ColoredString('RED', '\xe4')
assert '\xe4' in str(new_str) assert '\xe4' in str(new_str)
from clint.textui import puts from clint.textui import puts
puts(new_str)
def test_clint_force_color_env_var(self): def test_clint_force_color_env_var(self):
from clint.textui.colored import ColoredString from clint.textui.colored import ColoredString
@@ -57,6 +56,37 @@ class ColoredStringTestCase(unittest.TestCase):
new_str = ColoredString('RED', 'hello world') new_str = ColoredString('RED', 'hello world')
assert new_str.always_color == True assert new_str.always_color == True
def test_clint_unicode_radd(self):
from clint.textui.colored import ColoredString
inp_str = u'hello \u263A'
new_str = u'' + ColoredString('RED', inp_str)
assert inp_str.encode('utf-8') in new_str
class TextuiFormatterTestCase(unittest.TestCase):
def test_max_width(self):
def _test_n_rows_width(ins, rows, n_rows, max_width):
ins.assertEqual(len(rows), n_rows)
for row in rows:
ins.assertLessEqual(len(row), max_width)
from clint.textui.formatters import max_width
from clint.textui import colored
# normal text
text = ' '.join(['XXX'] * 3)
rows = max_width(text, 6).split('\n')
_test_n_rows_width(self, rows, 3, 6)
rows = max_width(text, 7).split('\n')
_test_n_rows_width(self, rows, 2, 7)
# colored text
c_text = colored.yellow(text)
rows = max_width(c_text, 6).split('\n')
_test_n_rows_width(self, rows, 3, 6)
rows = max_width(c_text, 7).split('\n')
_test_n_rows_width(self, rows, 2, 7)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()
+1 -1
View File
@@ -1,5 +1,5 @@
[tox] [tox]
envlist = py26,py27,py3 envlist = py26,py27,py32,py33
[testenv] [testenv]
commands=py.test --junitxml=junit-{envname}.xml commands=py.test --junitxml=junit-{envname}.xml