52 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
Jason Piper fa79d0d4ea v0.5.0 2015-08-25 22:07:27 +08:00
Joshua "jag" Ginsberg a09b1efa76 Support password inputs in textui.prompt.query 2015-04-17 11:23:10 -04:00
kennethreitz 140d85898d Merge pull request #134 from dstrohl/master
Added option prompt
2015-01-09 13:40:32 -05:00
kennethreitz 93d10a8acb Merge pull request #132 from jonasstein/master
Update setup.py
2015-01-09 13:39:38 -05:00
kennethreitz 9392b77dcd Merge pull request #133 from bahattincinic/readme
Typo in readme example ref #115
2015-01-09 13:39:30 -05:00
kennethreitz 1162b46f0b Merge pull request #136 from hickford/patch-2
Clarify Python version support
2015-01-09 13:39:21 -05:00
Jason Piper 82753f5172 Merge pull request #135 from hickford/patch-1
Fix classifiers not appearing on PyPI
2015-01-07 21:13:17 +00:00
Matt Hickford 714d06ecfa Clarify Python version support
Tested Python 3.3 and 3.4 at https://travis-ci.org/hickford/clint/builds/46098963
2015-01-06 17:55:55 +00:00
Matt Hickford c391eae023 Fix classifiers not appearing on PyPI
The classifiers weren't appearing on PyPI. https://pypi.python.org/pypi/clint/

This usually fixes it.
2015-01-06 17:46:37 +00:00
dstrohl 1c1f1c93f9 Added option prompt 2015-01-02 21:32:42 -08:00
Bahattin Cinic f06e164fc6 Typo in readme example ref #115 2015-01-02 23:57:17 +02:00
Jonas Stein a226b3f2dc Update setup.py
clint = "Command Line Interface Tools" tells me the README
2014-12-27 18:54:20 +01:00
Jason Piper e3f283ed6e fix gitignore and docs 2014-10-19 20:30:39 +01:00
Jason Piper 6a417e5bdf v0.4.1 2014-10-12 00:10:07 +01:00
Jason Piper 7431c17fe4 Decision to hide must be at runtime, not at import 2014-10-11 23:57:59 +01: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
37 changed files with 352 additions and 67 deletions
+36 -10
View File
@@ -1,11 +1,37 @@
.idea *.py[cod]
.project
.settings
.pydevproject
MANIFEST
*.pyc
.tox
build/
clint.egg-info/
dist/
# Packages
*.egg
*.egg-info
dist
build
eggs
parts
bin
var
sdist
develop-eggs
.installed.cfg
lib
lib64
# Installer logs
pip-log.txt
# Unit test / coverage reports
.coverage
.tox
nosetests.xml
# Translations
*.mo
# Mr Developer
.mr.developer.cfg
.project
.pydevproject
*.DS_Store
*.dylib
.idea/
docs/_*
+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>
+23 -2
View File
@@ -1,6 +1,20 @@
History History
------- -------
0.5.1
+++++
* Fix line width calculation in max_width when using coloured text (thanks to @wkentaro)
0.5.0
+++++
* Added option prompt
0.4.1
+++++
* Fix bug in logic that decides whether progress bars should be hidden or not
0.4.0 0.4.0
+++++ +++++
* clint.textui.prompt now has a query function with validators! (thanks to @aeby) - see `examples/prompt.py` * clint.textui.prompt now has a query function with validators! (thanks to @aeby) - see `examples/prompt.py`
@@ -12,39 +26,47 @@ History
+++++ +++++
* Clint now obeys the CLINT_FORCE_COLOR environmental variable * Clint now obeys the CLINT_FORCE_COLOR environmental variable
0.3.6 0.3.6
+++++ +++++
* Fixed faulty PyPI deployment * Fixed faulty PyPI deployment
0.3.5 0.3.5
+++++ +++++
* progress.bar is now a context manager - doesn't require an iterable anymore (thanks to @jric) * progress.bar is now a context manager - doesn't require an iterable anymore (thanks to @jric)
* Bug fixes * Bug fixes
0.3.4 0.3.4
+++++ +++++
* Fixed Python 3 basestring deprecation * Fixed Python 3 basestring deprecation
* Fixed examples * Fixed examples
0.3.3 0.3.3
+++++ +++++
* Fixed Python 3 build issues * Fixed Python 3 build issues
* Fixed README and HISTORY being installed to /usr * Fixed README and HISTORY being installed to /usr
* Support added for bold text * Support added for bold text
0.3.2 0.3.2
+++++ +++++
* Unknown * Unknown
0.3.1 0.3.1
+++++ +++++
* Unknown * Unknown
0.3.0 0.3.0
+++++ +++++
* Python 3 support! * Python 3 support!
0.2.4 0.2.4
+++++ +++++
@@ -55,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
@@ -102,7 +124,6 @@ History
* Lots of Examples * Lots of Examples
0.1.0 (2011-03-20) 0.1.0 (2011-03-20)
++++++++++++++++++ ++++++++++++++++++
+2
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
+4 -3
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:
----------------- -----------------
@@ -74,7 +75,7 @@ I want to quote my console text (like email). ::
I want to color my console text. :: I want to color my console text. ::
>>> from clint.textui import colored >>> from clint.textui import colored, puts
>>> puts(colored.red('red text')) >>> puts(colored.red('red text'))
red text red text
+2 -2
View File
@@ -26,8 +26,8 @@ from .pipes import piped_in
__title__ = 'clint' __title__ = 'clint'
__version__ = '0.4.0' __version__ = '0.5.1'
__build__ = 0x000400 __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)
+70 -8
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,16 +35,71 @@ 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)
@@ -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))
+6 -10
View File
@@ -14,11 +14,6 @@ import sys
import time import time
STREAM = sys.stderr STREAM = sys.stderr
# Only show bar in terminals by default (better for piping, logging etc.)
try:
HIDE_DEFAULT = not STREAM.isatty()
except AttributeError: # output does not support isatty()
HIDE_DEFAULT = True
BAR_TEMPLATE = '%s[%s%s] %i/%i - %s\r' BAR_TEMPLATE = '%s[%s%s] %i/%i - %s\r'
MILL_TEMPLATE = '%s %s %i/%i\r' MILL_TEMPLATE = '%s %s %i/%i\r'
@@ -48,6 +43,7 @@ class Bar(object):
self.label = label self.label = label
self.width = width self.width = width
self.hide = hide self.hide = hide
# Only show bar in terminals by default (better for piping, logging etc.)
if hide is None: if hide is None:
try: try:
self.hide = not STREAM.isatty() self.hide = not STREAM.isatty()
@@ -107,21 +103,21 @@ class Bar(object):
return time.strftime('%H:%M:%S', time.gmtime(seconds)) return time.strftime('%H:%M:%S', time.gmtime(seconds))
def bar(it, label='', width=32, hide=HIDE_DEFAULT, empty_char=BAR_EMPTY_CHAR, def bar(it, label='', width=32, hide=None, empty_char=BAR_EMPTY_CHAR,
filled_char=BAR_FILLED_CHAR, expected_size=None, every=1): filled_char=BAR_FILLED_CHAR, expected_size=None, every=1):
"""Progress iterator. Wrap your iterables with it.""" """Progress iterator. Wrap your iterables with it."""
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
bar.show(i + 1) bar.show(i + 1)
def dots(it, label='', hide=HIDE_DEFAULT, every=1): def dots(it, label='', hide=None, every=1):
"""Progress iterator. Prints a dot for each item being iterated""" """Progress iterator. Prints a dot for each item being iterated"""
count = 0 count = 0
@@ -143,7 +139,7 @@ def dots(it, label='', hide=HIDE_DEFAULT, every=1):
STREAM.flush() STREAM.flush()
def mill(it, label='', hide=HIDE_DEFAULT, expected_size=None, every=1): def mill(it, label='', hide=None, expected_size=None, every=1):
"""Progress iterator. Prints a mill while iterating over the items.""" """Progress iterator. Prints a mill while iterating over the items."""
def _mill_char(_i): def _mill_char(_i):
+97 -3
View File
@@ -11,10 +11,11 @@ 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
from .validators import RegexValidator from .validators import RegexValidator, OptionValidator
try: try:
raw_input raw_input
@@ -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 = ''
@@ -88,3 +90,95 @@ def query(prompt, default='', validators=None, batch=False):
return user_input return user_input
except Exception as e: except Exception as e:
puts(yellow(e.message)) puts(yellow(e.message))
def options(prompt, options, default=None, batch=False):
'''
:param prompt:
:param options:
this can be either a list of strings, in which case it will be presented like:
prompt:
(1) this is the first string
(2) this is the second string
(3) this is the third string
please select 1-3:
or a list of dictionaries in the format of:
{ { 'selector' : 'this is what the user will enter to select the option'
'prompt': 'this is the string that will be displayed, this can be omitted if the selector is also a prompt',
'return': 'this is what is returned to the calling procedure, if omitted, the option selector will be used' }
so, to replicate the above, the dict could look like:
[ {'selector':1,'prompt':'this is the first string','return':1},
{'selector':2,'prompt':'this is the second string','return':2},
{'selector':3,'prompt':'this is the third string'}
:param default: should be set to the default selector (if desired)
:param batch: True/False, will auto-return the default
:return:
'''
# Build fix options and build validator
validator_list = []
return_dict = {}
if isinstance(options[0],dict):
for item in options:
item['selector'] = str(item['selector'])
item['prompt'] = str(item['prompt'])
if 'return' not in item:
item['return'] = item['selector']
validator_list.append(item['selector'])
return_dict[item['selector']] = item['return']
else:
options_strings = options
options = []
for key, opt in enumerate(options_strings):
item = {}
item['selector'] = str(key+1)
item['prompt'] = str(opt)
item['return'] = key+1
return_dict[item['selector']] = item['return']
validator_list.append(item['selector'])
options.append(item)
validators = [OptionValidator(validator_list)]
# Let's build the prompt
prompt += '\n'
# building the options list
for o in options:
prompt += '[{selector}] {prompt}\n'.format(**o)
prompt += '\n'
if default:
prompt += '[' + default + '] '
# If input is not valid keep asking
while True:
# If batch option is True then auto reply
# with default input
if not batch:
user_input = raw_input(prompt).strip() or default
else:
print(prompt)
user_input = ''
# Validate the user input
try:
for validator in validators:
user_input = validator(user_input)
# convert user input to defined return value
user_input = return_dict[user_input]
return user_input
except Exception as e:
puts(yellow(e.message))
+18
View File
@@ -102,3 +102,21 @@ class IntegerValidator(object):
return int(value) return int(value)
except (TypeError, ValueError): except (TypeError, ValueError):
raise ValidationError(self.message) raise ValidationError(self.message)
class OptionValidator(object):
message = 'Select from the list of valid options.'
def __init__(self, options, message=None):
self.options = options
if message is not None:
self.message = message
def __call__(self, value):
"""
Validates that the input is in the options list.
"""
if value in self.options:
return value
else:
raise ValidationError(self.message)
+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
-1
View File
@@ -1 +0,0 @@
_build/*
View File
View File
-3
View File
@@ -1,3 +0,0 @@
*.pyc
*.pyo
.DS_Store
+2 -2
View File
@@ -19,7 +19,7 @@ import clint
# If extensions (or modules to document with autodoc) are in another directory, # If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the # add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here. # documentation root, use os.path.abspath to make it absolute, like shown here.
sys.path.append(os.path.abspath('_themes')) sys.path.append(os.path.abspath('themes'))
@@ -104,7 +104,7 @@ html_theme = 'kr'
#html_theme_options = {} #html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory. # Add any paths that contain custom themes here, relative to this directory.
html_theme_path = ['_themes'] html_theme_path = ['themes']
# The name for this set of Sphinx documents. If None, it defaults to # The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation". # "<project> v<release> documentation".
View File
+3 -1
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
@@ -18,5 +20,5 @@ with indent(4, quote='>>>'):
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)
+8 -1
View File
@@ -15,7 +15,14 @@ if __name__ == '__main__':
# Set validators to an empty list for an optional input # Set validators to an empty list for an optional input
language = prompt.query("Your favorite tool (optional)?", validators=[]) language = prompt.query("Your favorite tool (optional)?", validators=[])
# Shows a list of options to select from
inst_options = [{'selector':'1','prompt':'Full','return':'full'},
{'selector':'2','prompt':'Partial','return':'partial'},
{'selector':'3','prompt':'None','return':'no install'}]
inst = prompt.options("Full or Partial Install", inst_options)
# Use a default value and a validator # Use a default value and a validator
path = prompt.query('Installation Path', default='/usr/local/bin/', validators=[validators.PathValidator()]) path = prompt.query('Installation Path', default='/usr/local/bin/', validators=[validators.PathValidator()])
puts(colored.blue('Hi {0}. Install {1} to {2}'.format(name, language or 'nothing', path))) puts(colored.blue('Hi {0}. Install {1} {2} to {3}'.format(name, inst, language or 'nothing', path)))
+2
View File
@@ -0,0 +1,2 @@
[bdist_wheel]
universal=1
+6 -3
View File
@@ -24,7 +24,7 @@ required = ['args']
setup( setup(
name='clint', name='clint',
version=clint.__version__, version=clint.__version__,
description='Python Command-line Application Tools', description='Python Command Line Interface Tools',
long_description=open('README.rst').read() + '\n\n' + long_description=open('README.rst').read() + '\n\n' +
open('HISTORY.rst').read(), open('HISTORY.rst').read(),
author='Kenneth Reitz', author='Kenneth Reitz',
@@ -37,7 +37,7 @@ setup(
], ],
install_requires=required, install_requires=required,
license='ISC', license='ISC',
classifiers=( classifiers=[
# 'Development Status :: 5 - Production/Stable', # 'Development Status :: 5 - Production/Stable',
'Environment :: Console', 'Environment :: Console',
'Intended Audience :: Developers', 'Intended Audience :: Developers',
@@ -50,6 +50,9 @@ setup(
'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.1', 'Programming Language :: Python :: 3.1',
'Programming Language :: Python :: 3.2', 'Programming Language :: Python :: 3.2',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Topic :: Terminals :: Terminal Emulators/X Terminals', 'Topic :: Terminals :: Terminal Emulators/X Terminals',
), ],
test_suite='test_clint',
) )
+31 -1
View File
@@ -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