mirror of
https://github.com/kennethreitz/clint.git
synced 2026-06-05 14:50:17 +00:00
Compare commits
52 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9d3693d644 | |||
| ee695135a7 | |||
| e4ba837bad | |||
| 3b77ef3b43 | |||
| 2698af12dd | |||
| 195ab0de4d | |||
| b16b2248cd | |||
| dc8fbfd355 | |||
| 8f42b40900 | |||
| 96013432d9 | |||
| 84ce2ed9b1 | |||
| 8c3cbe984b | |||
| d0fe6df171 | |||
| 7865d7a375 | |||
| 0931dbff9f | |||
| 8dc046b9c7 | |||
| 39322ea11f | |||
| a190f64e3c | |||
| a7a28da410 | |||
| a1203ff9d9 | |||
| 16e50a62e1 | |||
| a173f763d0 | |||
| e101c56eed | |||
| 52ff92d7d5 | |||
| 34ec848479 | |||
| 2bd5aef5bc | |||
| a47ed4f711 | |||
| d0a5237afe | |||
| d6cb52f8b3 | |||
| fa79d0d4ea | |||
| a09b1efa76 | |||
| 140d85898d | |||
| 93d10a8acb | |||
| 9392b77dcd | |||
| 1162b46f0b | |||
| 82753f5172 | |||
| 714d06ecfa | |||
| c391eae023 | |||
| 1c1f1c93f9 | |||
| f06e164fc6 | |||
| a226b3f2dc | |||
| e3f283ed6e | |||
| 6a417e5bdf | |||
| 7431c17fe4 | |||
| 85d5f52549 | |||
| 7be8140d91 | |||
| fb96edf52f | |||
| 439de410c0 | |||
| 5a88ee3a52 | |||
| 3077b0f53e | |||
| 5e7a191957 | |||
| 6aedd380cf |
+36
-10
@@ -1,11 +1,37 @@
|
||||
.idea
|
||||
.project
|
||||
.settings
|
||||
.pydevproject
|
||||
MANIFEST
|
||||
*.pyc
|
||||
.tox
|
||||
build/
|
||||
clint.egg-info/
|
||||
dist/
|
||||
*.py[cod]
|
||||
|
||||
# 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
@@ -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
|
||||
@@ -31,3 +31,4 @@ Patches and Suggestions
|
||||
- Eric Anderson
|
||||
- Joshua Richardson
|
||||
- Brandon Liu <thenovices>
|
||||
- Kentaro Wada <www.kentaro.wada@gmail.com>
|
||||
|
||||
+23
-2
@@ -1,6 +1,20 @@
|
||||
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
|
||||
+++++
|
||||
* 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
|
||||
|
||||
|
||||
0.3.6
|
||||
+++++
|
||||
* Fixed faulty PyPI deployment
|
||||
|
||||
|
||||
0.3.5
|
||||
+++++
|
||||
* progress.bar is now a context manager - doesn't require an iterable anymore (thanks to @jric)
|
||||
* Bug fixes
|
||||
|
||||
|
||||
0.3.4
|
||||
+++++
|
||||
* Fixed Python 3 basestring deprecation
|
||||
* Fixed examples
|
||||
|
||||
|
||||
0.3.3
|
||||
+++++
|
||||
* Fixed Python 3 build issues
|
||||
* Fixed README and HISTORY being installed to /usr
|
||||
* Support added for bold text
|
||||
|
||||
|
||||
0.3.2
|
||||
+++++
|
||||
* Unknown
|
||||
|
||||
|
||||
0.3.1
|
||||
+++++
|
||||
* Unknown
|
||||
|
||||
|
||||
0.3.0
|
||||
+++++
|
||||
|
||||
* Python 3 support!
|
||||
|
||||
|
||||
0.2.4
|
||||
+++++
|
||||
|
||||
@@ -55,7 +77,7 @@ History
|
||||
0.2.3
|
||||
+++++
|
||||
|
||||
* Only init colors if they are used (iPython compatability)
|
||||
* Only init colors if they are used (iPython compatibility)
|
||||
* New progress module
|
||||
* Various bugfixes
|
||||
|
||||
@@ -102,7 +124,6 @@ History
|
||||
* Lots of Examples
|
||||
|
||||
|
||||
|
||||
0.1.0 (2011-03-20)
|
||||
++++++++++++++++++
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
ISC License
|
||||
|
||||
Copyright (c) 2011, Kenneth Reitz <me@kennethreitz.com>
|
||||
|
||||
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
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
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.
|
||||
|
||||
+4
-3
@@ -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
|
||||
@@ -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.
|
||||
|
||||
|
||||
.. image:: https://travis-ci.org/kennethreitz/clint.png?branch=master
|
||||
:target: https://travis-ci.org/kennethreitz/clint
|
||||
|
||||
Current Features:
|
||||
-----------------
|
||||
@@ -74,7 +75,7 @@ I want to quote my console text (like email). ::
|
||||
|
||||
I want to color my console text. ::
|
||||
|
||||
>>> from clint.textui import colored
|
||||
>>> from clint.textui import colored, puts
|
||||
|
||||
>>> puts(colored.red('red text'))
|
||||
red text
|
||||
|
||||
+2
-2
@@ -26,8 +26,8 @@ from .pipes import piped_in
|
||||
|
||||
|
||||
__title__ = 'clint'
|
||||
__version__ = '0.4.0'
|
||||
__build__ = 0x000400
|
||||
__version__ = '0.5.1'
|
||||
__build__ = 0x000501
|
||||
__author__ = 'Kenneth Reitz'
|
||||
__license__ = 'ISC'
|
||||
__copyright__ = 'Copyright 2012 Kenneth Reitz'
|
||||
|
||||
@@ -18,6 +18,7 @@ import sys
|
||||
PY3 = sys.version_info[0] >= 3
|
||||
|
||||
from ..packages import colorama
|
||||
from ..utils import basestring
|
||||
|
||||
__all__ = (
|
||||
'red', 'green', 'yellow', 'blue',
|
||||
@@ -42,7 +43,10 @@ class ColoredString(object):
|
||||
"""Enhanced string for __len__ operations on Colored output."""
|
||||
def __init__(self, color, s, always_color=False, bold=False):
|
||||
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.always_color = always_color
|
||||
self.bold = bold
|
||||
@@ -93,10 +97,7 @@ class ColoredString(object):
|
||||
__str__ = __unicode__
|
||||
else:
|
||||
def __str__(self):
|
||||
value = self.color_str
|
||||
if isinstance(value, bytes):
|
||||
return value
|
||||
return value.encode('utf8')
|
||||
return self.color_str
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self.color_str)
|
||||
|
||||
@@ -15,7 +15,7 @@ import sys
|
||||
|
||||
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 ..utils import tsplit
|
||||
|
||||
@@ -53,6 +53,11 @@ def _indent(indent=0, quote='', indent_char=' '):
|
||||
|
||||
def puts(s='', newline=True, stream=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:
|
||||
s = tsplit(s, NEWLINES)
|
||||
s = map(str, s)
|
||||
|
||||
@@ -9,12 +9,14 @@ Core TextUI functionality for text formatting.
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import
|
||||
from contextlib import contextmanager
|
||||
|
||||
from .colored import ColoredString, clean
|
||||
from ..utils import tsplit, schunk
|
||||
|
||||
|
||||
NEWLINES = ('\n', '\r', '\r\n')
|
||||
MAX_WIDTHS = []
|
||||
|
||||
|
||||
def min_width(string, cols, padding=' '):
|
||||
@@ -33,17 +35,72 @@ def min_width(string, cols, padding=' '):
|
||||
return '\n'.join(stack)
|
||||
|
||||
|
||||
def max_width(string, cols, separator='\n'):
|
||||
"""Returns a freshly formatted """
|
||||
def _get_max_width_context():
|
||||
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)
|
||||
|
||||
if is_color:
|
||||
offset = 10
|
||||
string_copy = string._new('')
|
||||
else:
|
||||
offset = 0
|
||||
|
||||
string = string.s
|
||||
|
||||
stack = tsplit(string, NEWLINES)
|
||||
|
||||
for i, substring in enumerate(stack):
|
||||
@@ -56,31 +113,36 @@ def max_width(string, cols, separator='\n'):
|
||||
_row_i = 0
|
||||
|
||||
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] += ' '
|
||||
|
||||
elif len(word) > (cols - offset):
|
||||
elif len(word) > cols:
|
||||
|
||||
# ensure empty row
|
||||
if len(_row[_row_i]):
|
||||
_row[_row_i] = _row[_row_i].rstrip()
|
||||
_row.append('')
|
||||
_row_i += 1
|
||||
|
||||
chunks = schunk(word, (cols + offset))
|
||||
chunks = schunk(word, cols)
|
||||
for i, chunk in enumerate(chunks):
|
||||
if not (i + 1) == len(chunks):
|
||||
_row[_row_i] += chunk
|
||||
_row[_row_i] = _row[_row_i].rstrip()
|
||||
_row.append('')
|
||||
_row_i += 1
|
||||
else:
|
||||
_row[_row_i] += chunk
|
||||
_row[_row_i] += ' '
|
||||
else:
|
||||
_row[_row_i] = _row[_row_i].rstrip()
|
||||
_row.append('')
|
||||
_row_i += 1
|
||||
_row[_row_i] += word
|
||||
_row[_row_i] += ' '
|
||||
else:
|
||||
_row[_row_i] = _row[_row_i].rstrip()
|
||||
|
||||
_row = map(str, _row)
|
||||
_stack.append(separator.join(_row))
|
||||
|
||||
@@ -14,11 +14,6 @@ import sys
|
||||
import time
|
||||
|
||||
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'
|
||||
MILL_TEMPLATE = '%s %s %i/%i\r'
|
||||
@@ -48,6 +43,7 @@ class Bar(object):
|
||||
self.label = label
|
||||
self.width = width
|
||||
self.hide = hide
|
||||
# Only show bar in terminals by default (better for piping, logging etc.)
|
||||
if hide is None:
|
||||
try:
|
||||
self.hide = not STREAM.isatty()
|
||||
@@ -107,21 +103,21 @@ class Bar(object):
|
||||
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):
|
||||
"""Progress iterator. Wrap your iterables with it."""
|
||||
|
||||
count = len(it) if expected_size is None else expected_size
|
||||
|
||||
with Bar(label=label, width=width, hide=hide, empty_char=BAR_EMPTY_CHAR,
|
||||
filled_char=BAR_FILLED_CHAR, expected_size=count, every=every) \
|
||||
with Bar(label=label, width=width, hide=hide, empty_char=empty_char,
|
||||
filled_char=filled_char, expected_size=count, every=every) \
|
||||
as bar:
|
||||
for i, item in enumerate(it):
|
||||
yield item
|
||||
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"""
|
||||
|
||||
count = 0
|
||||
@@ -143,7 +139,7 @@ def dots(it, label='', hide=HIDE_DEFAULT, every=1):
|
||||
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."""
|
||||
|
||||
def _mill_char(_i):
|
||||
|
||||
+97
-3
@@ -11,10 +11,11 @@ Module for simple interactive prompts handling
|
||||
from __future__ import absolute_import, print_function
|
||||
|
||||
from re import match, I
|
||||
import getpass
|
||||
|
||||
from .core import puts
|
||||
from .colored import yellow
|
||||
from .validators import RegexValidator
|
||||
from .validators import RegexValidator, OptionValidator
|
||||
|
||||
try:
|
||||
raw_input
|
||||
@@ -59,7 +60,7 @@ def yn(prompt, default='y', batch=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
|
||||
if validators is None:
|
||||
validators = [RegexValidator(r'.+')]
|
||||
@@ -76,7 +77,8 @@ def query(prompt, default='', validators=None, batch=False):
|
||||
# If batch option is True then auto reply
|
||||
# with default input
|
||||
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:
|
||||
print(prompt)
|
||||
user_input = ''
|
||||
@@ -88,3 +90,95 @@ def query(prompt, default='', validators=None, batch=False):
|
||||
return user_input
|
||||
except Exception as e:
|
||||
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))
|
||||
|
||||
@@ -102,3 +102,21 @@ class IntegerValidator(object):
|
||||
return int(value)
|
||||
except (TypeError, ValueError):
|
||||
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
@@ -17,7 +17,7 @@ from os import makedirs
|
||||
from glob import glob
|
||||
|
||||
try:
|
||||
basestring
|
||||
basestring = basestring
|
||||
except NameError:
|
||||
basestring = str
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
_build/*
|
||||
Vendored
Vendored
@@ -1,3 +0,0 @@
|
||||
*.pyc
|
||||
*.pyo
|
||||
.DS_Store
|
||||
+2
-2
@@ -19,7 +19,7 @@ import clint
|
||||
# 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
|
||||
# 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 = {}
|
||||
|
||||
# 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
|
||||
# "<project> v<release> documentation".
|
||||
|
||||
+4
-2
@@ -1,6 +1,8 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
@@ -17,6 +19,6 @@ with indent(4, quote='>>>'):
|
||||
puts(colored.red('Files detected: ') + str(args.files))
|
||||
puts(colored.red('NOT Files detected: ') + str(args.not_files))
|
||||
puts(colored.red('Grouped Arguments: ') + str(dict(args.grouped)))
|
||||
|
||||
print
|
||||
|
||||
print()
|
||||
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
#! /usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
sys.path.insert(0, os.path.abspath('..'))
|
||||
|
||||
from clint.arguments import Args
|
||||
from clint.textui import puts, colored
|
||||
|
||||
@@ -8,6 +13,6 @@ all_args = Args().grouped
|
||||
|
||||
for item in all_args:
|
||||
if item is not '_':
|
||||
puts(colored.red("key:%s"%item))
|
||||
puts(colored.red("key:%s" % item))
|
||||
print(all_args[item].all)
|
||||
|
||||
|
||||
+8
-1
@@ -15,7 +15,14 @@ if __name__ == '__main__':
|
||||
# Set validators to an empty list for an optional input
|
||||
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
|
||||
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)))
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ required = ['args']
|
||||
setup(
|
||||
name='clint',
|
||||
version=clint.__version__,
|
||||
description='Python Command-line Application Tools',
|
||||
description='Python Command Line Interface Tools',
|
||||
long_description=open('README.rst').read() + '\n\n' +
|
||||
open('HISTORY.rst').read(),
|
||||
author='Kenneth Reitz',
|
||||
@@ -37,7 +37,7 @@ setup(
|
||||
],
|
||||
install_requires=required,
|
||||
license='ISC',
|
||||
classifiers=(
|
||||
classifiers=[
|
||||
# 'Development Status :: 5 - Production/Stable',
|
||||
'Environment :: Console',
|
||||
'Intended Audience :: Developers',
|
||||
@@ -50,6 +50,9 @@ setup(
|
||||
'Programming Language :: Python :: 3',
|
||||
'Programming Language :: Python :: 3.1',
|
||||
'Programming Language :: Python :: 3.2',
|
||||
'Programming Language :: Python :: 3.3',
|
||||
'Programming Language :: Python :: 3.4',
|
||||
'Topic :: Terminals :: Terminal Emulators/X Terminals',
|
||||
),
|
||||
],
|
||||
test_suite='test_clint',
|
||||
)
|
||||
|
||||
+36
-6
@@ -18,25 +18,25 @@ class ClintTestCase(unittest.TestCase):
|
||||
pass
|
||||
|
||||
class ColoredStringTestCase(unittest.TestCase):
|
||||
|
||||
|
||||
def setUp(self):
|
||||
from clint.textui.colored import ColoredString
|
||||
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
|
||||
|
||||
def test_split(self):
|
||||
from clint.textui.colored import ColoredString
|
||||
new_str = ColoredString('red', "hello world")
|
||||
output = new_str.split()
|
||||
assert output[0].s == "hello"
|
||||
|
||||
|
||||
def test_find(self):
|
||||
from clint.textui.colored import ColoredString
|
||||
new_str = ColoredString('blue', "hello world")
|
||||
output = new_str.find('h')
|
||||
self.assertEqual(output, 0)
|
||||
|
||||
|
||||
def test_replace(self):
|
||||
from clint.textui.colored import ColoredString
|
||||
new_str = ColoredString('green', "hello world")
|
||||
@@ -49,7 +49,6 @@ class ColoredStringTestCase(unittest.TestCase):
|
||||
new_str = ColoredString('RED', '\xe4')
|
||||
assert '\xe4' in str(new_str)
|
||||
from clint.textui import puts
|
||||
puts(new_str)
|
||||
|
||||
def test_clint_force_color_env_var(self):
|
||||
from clint.textui.colored import ColoredString
|
||||
@@ -57,6 +56,37 @@ class ColoredStringTestCase(unittest.TestCase):
|
||||
new_str = ColoredString('RED', 'hello world')
|
||||
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__':
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user