1 Commits

Author SHA1 Message Date
Kenneth Reitz e172a1e282 v0.3.2 2013-12-02 22:16:40 -05:00
15 changed files with 117 additions and 215 deletions
-6
View File
@@ -1,11 +1,5 @@
.idea
.project
.settings
.pydevproject
MANIFEST
*.pyc
.tox
build/
clint.egg-info/
dist/
-5
View File
@@ -6,10 +6,6 @@ Development Lead
- Kenneth Reitz <me@kennethreitz.com>
Maintainers
```````````
- Jason Piper <j.piper@me.com>
Patches and Suggestions
```````````````````````
@@ -29,4 +25,3 @@ Patches and Suggestions
- Justin Barber <barber.justin (at) gmail>
- Dmitry Medvinsky
- Eric Anderson
- Joshua Richardson
-32
View File
@@ -1,38 +1,6 @@
History
-------
0.3.7
+++++
* 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
+++++
+3 -8
View File
@@ -91,9 +91,7 @@ I want to get data piped to stdin. ::
I want to get the first commandline argument passed in. ::
>>> from clint import arguments
>>> args = arguments.Args()
>>> args.get(0)
>>> clint.args.get(0)
# if no argument was passed, get returns None
@@ -109,10 +107,6 @@ I want to store a configuration file. ::
# Windows: 'C:\\Users\\appuser\\AppData\\Local\\Company\\AppName\\config.ini'
# Linux: '/home/appuser/.config/appname/config.ini'
I want to force color output even if stdout is not a TTY:
$ export CLINT_FORCE_COLOR=1
Installation
------------
@@ -153,7 +147,7 @@ Contribute
----------
If you'd like to contribute, simply fork `the repository`_, commit your changes
to the **master** branch (or branch off of it), and send a pull request. Make
to the **develop** branch (or branch off of it), and send a pull request. Make
sure you add yourself to AUTHORS_.
@@ -161,6 +155,7 @@ Roadmap
-------
- Unittests
- Sphinx Documentation
- Python 2.5, 3.1, 3.2 Support
+2 -2
View File
@@ -26,8 +26,8 @@ from .pipes import piped_in
__title__ = 'clint'
__version__ = '0.3.7'
__build__ = 0x000307
__version__ = '0.3.2'
__build__ = 0x000302
__author__ = 'Kenneth Reitz'
__license__ = 'ISC'
__copyright__ = 'Copyright 2012 Kenneth Reitz'
+29 -40
View File
@@ -11,7 +11,6 @@ This module provides a simple and elegant wrapper for colorama.
from __future__ import absolute_import
import os
import re
import sys
@@ -38,36 +37,29 @@ else:
DISABLE_COLOR = False
class ColoredString(object):
"""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):
super(ColoredString, self).__init__()
self.s = s
self.color = color
self.always_color = always_color
self.bold = bold
if os.environ.get('CLINT_FORCE_COLOR'):
self.always_color = True
def __getattr__(self, att):
def func_help(*args, **kwargs):
result = getattr(self.s, att)(*args, **kwargs)
try:
is_result_string = isinstance(result, basestring)
except NameError:
is_result_string = isinstance(result, str)
if is_result_string:
return self._new(result)
elif isinstance(result, list):
return [self._new(x) for x in result]
else:
return result
return func_help
def func_help(*args, **kwargs):
result = getattr(self.s, att)(*args, **kwargs)
if isinstance(result, basestring):
return self._new(result)
elif isinstance(result, list):
return [self._new(x) for x in result]
else:
return result
return func_help
@property
def color_str(self):
style = 'BRIGHT' if self.bold else 'NORMAL'
c = '%s%s%s%s%s' % (getattr(colorama.Fore, self.color), getattr(colorama.Style, style), self.s, colorama.Fore.RESET, getattr(colorama.Style, 'NORMAL'))
c = '%s%s%s' % (getattr(colorama.Fore, self.color), self.s, colorama.Fore.RESET)
if self.always_color:
return c
@@ -93,10 +85,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 unicode(self).encode('utf8')
def __iter__(self):
return iter(self.color_str)
@@ -124,29 +113,29 @@ def clean(s):
return txt
def black(string, always=False, bold=False):
return ColoredString('BLACK', string, always_color=always, bold=bold)
def black(string, always=False):
return ColoredString('BLACK', string, always_color=always)
def red(string, always=False, bold=False):
return ColoredString('RED', string, always_color=always, bold=bold)
def red(string, always=False):
return ColoredString('RED', string, always_color=always)
def green(string, always=False, bold=False):
return ColoredString('GREEN', string, always_color=always, bold=bold)
def green(string, always=False):
return ColoredString('GREEN', string, always_color=always)
def yellow(string, always=False, bold=False):
return ColoredString('YELLOW', string, always_color=always, bold=bold)
def yellow(string, always=False):
return ColoredString('YELLOW', string, always_color=always)
def blue(string, always=False, bold=False):
return ColoredString('BLUE', string, always_color=always, bold=bold)
def blue(string, always=False):
return ColoredString('BLUE', string, always_color=always)
def magenta(string, always=False, bold=False):
return ColoredString('MAGENTA', string, always_color=always, bold=bold)
def magenta(string, always=False):
return ColoredString('MAGENTA', string, always_color=always)
def cyan(string, always=False, bold=False):
return ColoredString('CYAN', string, always_color=always, bold=bold)
def cyan(string, always=False):
return ColoredString('CYAN', string, always_color=always)
def white(string, always=False, bold=False):
return ColoredString('WHITE', string, always_color=always, bold=bold)
def white(string, always=False):
return ColoredString('WHITE', string, always_color=always)
def disable():
"""Disables colors."""
+35 -70
View File
@@ -33,78 +33,43 @@ ETA_INTERVAL = 1
#How many intervals (excluding the current one) to calculate the simple moving average
ETA_SMA_WINDOW = 9
class Bar(object):
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.done()
return False # we're not surpressing exceptions
def __init__(self, label='', width=32, hide=None, empty_char=BAR_EMPTY_CHAR,
filled_char=BAR_FILLED_CHAR, expected_size=None, every=1):
self.label = label
self.width = width
self.hide = hide
if hide is None:
try:
self.hide = not STREAM.isatty()
except AttributeError: # output does not support isatty()
self.hide = True
self.empty_char = empty_char
self.filled_char = filled_char
self.expected_size = expected_size
self.every = every
self.start = time.time()
self.ittimes = []
self.eta = 0
self.etadelta = time.time()
self.etadisp = time.strftime('%H:%M:%S', time.gmtime(self.eta))
if (self.expected_size):
self.show(0)
def show(self, progress, count=None):
if count is not None:
self.expected_size = count
if self.expected_size is None:
raise Exception("expected_size not initialized")
if (time.time() - self.etadelta) > ETA_INTERVAL:
self.etadelta = time.time()
self.ittimes = \
self.ittimes[-ETA_SMA_WINDOW:]+\
[-(self.start-time.time())/(progress+1)]
self.eta = \
sum(self.ittimes)/float(len(self.ittimes)) * \
(self.expected_size-progress)
self.etadisp = time.strftime('%H:%M:%S', time.gmtime(self.eta))
x = int(self.width*progress/self.expected_size)
if not self.hide:
if ((progress % self.every)==0 or # True every "every" updates
(progress == self.expected_size)): # And when we're done
STREAM.write(BAR_TEMPLATE % (
self.label, self.filled_char*x,
self.empty_char*(self.width-x), progress,
self.expected_size, self.etadisp))
STREAM.flush()
def done(self):
if not self.hide:
STREAM.write('\n')
STREAM.flush()
def bar(it, label='', width=32, hide=HIDE_DEFAULT, 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) \
as bar:
def _show(_i):
if (time.time() - bar.etadelta) > ETA_INTERVAL:
bar.etadelta = time.time()
bar.ittimes = bar.ittimes[-ETA_SMA_WINDOW:]+[-(bar.start-time.time())/(_i+1)]
bar.eta = sum(bar.ittimes)/float(len(bar.ittimes)) * (count-_i)
bar.etadisp = time.strftime('%H:%M:%S', time.gmtime(bar.eta))
x = int(width*_i/count)
if not hide:
if ((_i % every)==0 or # True every "every" updates
(_i == count)): # And when we're done
STREAM.write(BAR_TEMPLATE % (
label, filled_char*x, empty_char*(width-x), _i, count, bar.etadisp))
STREAM.flush()
count = len(it) if expected_size is None else expected_size
bar.start = time.time()
bar.ittimes = []
bar.eta = 0
bar.etadelta = time.time()
bar.etadisp = time.strftime('%H:%M:%S', time.gmtime(bar.eta))
if count:
_show(0)
for i, item in enumerate(it):
yield item
_show(i+1)
if not hide:
STREAM.write('\n')
STREAM.flush()
for i, item in enumerate(it):
yield item
bar.show(i+1)
def dots(it, label='', hide=HIDE_DEFAULT, every=1):
"""Progress iterator. Prints a dot for each item being iterated"""
@@ -132,10 +97,10 @@ def mill(it, label='', hide=HIDE_DEFAULT, expected_size=None, every=1):
"""Progress iterator. Prints a mill while iterating over the items."""
def _mill_char(_i):
if _i >= count:
if _i == 100:
return ' '
else:
return MILL_CHARS[(_i / every) % len(MILL_CHARS)]
return MILL_CHARS[_i % len(MILL_CHARS)]
def _show(_i):
if not hide:
+8 -13
View File
@@ -8,34 +8,29 @@ Module for simple interactive prompts handling
"""
from __future__ import absolute_import, print_function
from __future__ import absolute_import
from re import match, I
try:
raw_input
except NameError:
raw_input = input
def yn(prompt, default='y', batch=False):
# A sanity check against default value
# If not y/n then y is assumed
# If not y/n then y is assumed
if default not in ['y', 'n']:
default = 'y'
# Let's build the prompt
choicebox = '[Y/n]' if default == 'y' else '[y/N]'
prompt = prompt + ' ' + choicebox + ' '
choicebox = '[Y/n]' if default == 'y' else '[y/N]'
prompt = prompt + ' ' + choicebox + ' '
# If input is not a yes/no variant or empty
# keep asking
while True:
# If batch option is True then auto reply
# If batch option is True then auto reply
# with default input
if not batch:
input = raw_input(prompt).strip()
else:
print(prompt)
print prompt
input = ''
# If input is empty default choice is assumed
@@ -44,7 +39,7 @@ def yn(prompt, default='y', batch=False):
return True
# Given 'yes' as input if default choice is y
# then return True, False otherwise
# then return True, False otherwise
if match('y(?:es)?', input, I):
return True if default == 'y' else False
+30 -8
View File
@@ -61,15 +61,37 @@ def mkdir_p(path):
def tsplit(string, delimiters):
"""Behaves str.split but supports tuples of delimiters."""
delimiters = tuple(delimiters)
if len(delimiters) < 1:
return [string,]
final_delimiter = delimiters[0]
for i in delimiters[1:]:
string = string.replace(i, final_delimiter)
return string.split(final_delimiter)
delimiters = tuple(delimiters)
stack = [string,]
for delimiter in delimiters:
for i, substring in enumerate(stack):
substack = substring.split(delimiter)
stack.pop(i)
for j, _substring in enumerate(substack):
stack.insert(i+j, _substring)
return stack
def schunk(string, size):
"""Splits string into n sized chunks."""
return [string[i:i+size] for i in range(0, len(string), size)]
stack = []
substack = []
current_count = 0
for char in string:
if not current_count < size:
stack.append(''.join(substack))
substack = []
current_count = 0
substack.append(char)
current_count += 1
if len(substack):
stack.append(''.join(substack))
return stack
Executable → Regular
+1 -3
View File
@@ -6,11 +6,9 @@ import os
sys.path.insert(0, os.path.abspath('..'))
from clint.arguments import Args
from clint import args
from clint.textui import puts, colored, indent
args = Args()
with indent(4, quote='>>>'):
puts(colored.red('Aruments passed in: ') + str(args.all))
puts(colored.red('Flags detected: ') + str(args.flags))
Executable → Regular
+2 -2
View File
@@ -1,10 +1,10 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
from clint.arguments import Args
from clint import args
from clint.textui import puts, colored
all_args = Args().grouped
all_args = args.grouped
for item in all_args:
if item is not '_':
-7
View File
@@ -14,13 +14,6 @@ from clint.textui import progress
if __name__ == '__main__':
for i in progress.bar(range(100)):
sleep(random() * 0.2)
with progress.Bar(label="nonlinear", expected_size=10) as bar:
last_val = 0
for val in (1,2,3,9,10):
sleep(2 * (val - last_val))
bar.show(val)
last_val = val
for i in progress.dots(range(100)):
sleep(random() * 0.2)
+1 -3
View File
@@ -11,12 +11,10 @@ try:
except:
import simplejson as json
from clint.arguments import Args
from clint import args
from clint import piped_in
from clint.textui import colored, puts, indent
args = Args()
if __name__ == '__main__':
puts('Test:')
+6
View File
@@ -11,6 +11,8 @@ except ImportError:
import clint
def publish():
"""Publish to PyPi"""
os.system("python setup.py sdist upload")
@@ -30,6 +32,10 @@ setup(
author='Kenneth Reitz',
author_email='me@kennethreitz.com',
url='https://github.com/kennethreitz/clint',
data_files=[
'README.rst',
'HISTORY.rst',
],
packages= [
'clint',
'clint.textui',
-16
View File
@@ -3,7 +3,6 @@
"""Clint Test Suite."""
import os
import unittest
@@ -43,20 +42,5 @@ class ColoredStringTestCase(unittest.TestCase):
output = new_str.replace("world", "universe")
assert output.s == "hello universe"
def test_py2_bytes_not_mangled(self):
from clint.textui.colored import ColoredString
# On python 2 make sure the same bytes come out as went in
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
os.environ['CLINT_FORCE_COLOR'] = "1"
new_str = ColoredString('RED', 'hello world')
assert new_str.always_color == True
if __name__ == '__main__':
unittest.main()