mirror of
https://github.com/kennethreitz/clint.git
synced 2026-06-05 14:50:17 +00:00
Compare commits
110 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 57955b9156 | |||
| f1ab574413 | |||
| 2aff70618c | |||
| 4b7688b220 | |||
| 03731d6ef2 | |||
| 8a2aed6c32 | |||
| 98cab56e97 | |||
| 13df32316f | |||
| 93c3f9a4e1 | |||
| 9f14dbb6c5 | |||
| 0e0284f967 | |||
| c5dbe0708e | |||
| 00b522510c | |||
| 4b98c46519 | |||
| e62f5657a5 | |||
| 8e17e8ce50 | |||
| 84dafbeabe | |||
| 5305d1e116 | |||
| 73b1bdd2d4 | |||
| 7bde48ce53 | |||
| a0e14e4181 | |||
| de2cbfca90 | |||
| c909d7dca0 | |||
| 6220552ebf | |||
| a9623213e3 | |||
| 77eab0c0e6 | |||
| 3d01b405b3 | |||
| 6c50b92cb3 | |||
| e00476d195 | |||
| fc463f16c3 | |||
| 9324af95b2 | |||
| 50294ea2dc | |||
| 56fe6138b6 | |||
| d22847fb95 | |||
| ce25cea7e8 | |||
| cab8004284 | |||
| c76cc35289 | |||
| 8e86e4c1fa | |||
| 858db011d8 | |||
| c111ba5d92 | |||
| 9e43717921 | |||
| 8e351ac4d0 | |||
| cb8bcee077 | |||
| 3df99a6a2b | |||
| 5b37fb544d | |||
| 099a506344 | |||
| d7fdbe85a9 | |||
| 7b2130e582 | |||
| f884841082 | |||
| 112ea81b51 | |||
| 399fa2bb24 | |||
| ab2f37219a | |||
| 464849e575 | |||
| acdddbabea | |||
| 1a11a670e7 | |||
| 1dc521de1a | |||
| 1e3888e530 | |||
| 2c8561a492 | |||
| 04f0cdd646 | |||
| 0bd5026d21 | |||
| b69ceb18d2 | |||
| e1bdaa4d0d | |||
| 8103032de8 | |||
| ab401e7af2 | |||
| fc841b0a61 | |||
| b591c3edc2 | |||
| 70c0680b8c | |||
| e7db8c7e37 | |||
| 944af48ba5 | |||
| a1808173d9 | |||
| c2aa315a58 | |||
| 3e03a9ceb9 | |||
| 02016e8b06 | |||
| a7e2d21273 | |||
| 911a84406e | |||
| afd410125d | |||
| e2a169ab9c | |||
| cfad07a774 | |||
| 48d9c16f0f | |||
| 86b196811f | |||
| d479ea3a3c | |||
| fc873deb3b | |||
| d4cb4e8c01 | |||
| 7c48045b57 | |||
| ea9b2186d5 | |||
| 761dce7237 | |||
| 72b04cf5af | |||
| 0378771f94 | |||
| 129fea5e4f | |||
| a9d1089bbd | |||
| 270afcca03 | |||
| c7f5296b13 | |||
| e8f6f7737a | |||
| 43b152cf0e | |||
| 0d0d482156 | |||
| 3a40b682f4 | |||
| 1d1bb71203 | |||
| b917e68837 | |||
| 66a6148088 | |||
| a95e803268 | |||
| 7e1c739755 | |||
| ec46d65bd2 | |||
| 73a9cd836b | |||
| c9bf3bac3a | |||
| 5f2df1218a | |||
| 526cf84ebb | |||
| 3709f090b4 | |||
| d6214ababb | |||
| ee089c2d39 | |||
| 53ec4c2e09 |
@@ -1,5 +1,11 @@
|
||||
.idea
|
||||
.project
|
||||
.settings
|
||||
.pydevproject
|
||||
MANIFEST
|
||||
*.pyc
|
||||
.tox
|
||||
build/
|
||||
clint.egg-info/
|
||||
dist/
|
||||
|
||||
|
||||
@@ -6,6 +6,10 @@ Development Lead
|
||||
|
||||
- Kenneth Reitz <me@kennethreitz.com>
|
||||
|
||||
Maintainers
|
||||
```````````
|
||||
|
||||
- Jason Piper <j.piper@me.com>
|
||||
|
||||
Patches and Suggestions
|
||||
```````````````````````
|
||||
@@ -16,4 +20,13 @@ Patches and Suggestions
|
||||
- Will Thames
|
||||
- Greg Haskins
|
||||
- Miguel Araujo <maraujop>
|
||||
- takluyver
|
||||
- takluyver
|
||||
- kracekumar
|
||||
- Alejandro Gómez <alejandrogomez>
|
||||
- Jason Piper <jpiper>
|
||||
- Gianluca Brindisi <gbrindisi>
|
||||
- Don Spaulding <donspauldingii@gmail.com>
|
||||
- Justin Barber <barber.justin (at) gmail>
|
||||
- Dmitry Medvinsky
|
||||
- Eric Anderson
|
||||
- Joshua Richardson
|
||||
|
||||
@@ -11,4 +11,4 @@ All functionality should be available in pure Python. Optional C (via Cython)
|
||||
implementations may be written for performance reasons, but should never
|
||||
replace the Python implementation.
|
||||
|
||||
Lastly, don't take yourself too seriously :)
|
||||
Lastly, don't take yourself too seriously :)
|
||||
|
||||
+32
@@ -1,6 +1,38 @@
|
||||
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
|
||||
+++++
|
||||
|
||||
|
||||
+12
-7
@@ -4,7 +4,7 @@ Clint: Python Command-line Application Tools
|
||||
**Clint** is a module filled with a set of awesome tools for developing
|
||||
commandline applications.
|
||||
|
||||
.. image:: https://github.com/kennethreitz/clint/raw/master/misc/clint.jpeg
|
||||
.. image:: https://raw.github.com/kennethreitz/clint/master/misc/clint.jpeg
|
||||
|
||||
**C** ommand
|
||||
**L** ine
|
||||
@@ -24,7 +24,7 @@ The world's easiest to use implicit argument system w/ chaining methods for filt
|
||||
|
||||
Run the various executables in examples_ to get a good feel for what Clint offers.
|
||||
|
||||
.. _examples: https://github.com/kennethreitz/clint/tree/develop/examples
|
||||
.. _examples: https://github.com/kennethreitz/clint/tree/master/examples
|
||||
|
||||
You'll never want to not use it.
|
||||
|
||||
@@ -70,7 +70,7 @@ I want to quote my console text (like email). ::
|
||||
>>> puts('pretty cool, eh?')
|
||||
|
||||
not indented text
|
||||
> indented text
|
||||
> quoted text
|
||||
> pretty cool, eh?
|
||||
|
||||
I want to color my console text. ::
|
||||
@@ -91,7 +91,9 @@ I want to get data piped to stdin. ::
|
||||
|
||||
I want to get the first commandline argument passed in. ::
|
||||
|
||||
>>> clint.args.get(0)
|
||||
>>> from clint import arguments
|
||||
>>> args = arguments.Args()
|
||||
>>> args.get(0)
|
||||
|
||||
# if no argument was passed, get returns None
|
||||
|
||||
@@ -107,6 +109,10 @@ 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
|
||||
------------
|
||||
@@ -147,7 +153,7 @@ Contribute
|
||||
----------
|
||||
|
||||
If you'd like to contribute, simply fork `the repository`_, commit your changes
|
||||
to the **develop** branch (or branch off of it), and send a pull request. Make
|
||||
to the **master** branch (or branch off of it), and send a pull request. Make
|
||||
sure you add yourself to AUTHORS_.
|
||||
|
||||
|
||||
@@ -155,9 +161,8 @@ Roadmap
|
||||
-------
|
||||
- Unittests
|
||||
- Sphinx Documentation
|
||||
- Python 2.5, 3.1, 3.2 Support
|
||||
|
||||
|
||||
|
||||
.. _`the repository`: http://github.com/kennethreitz/clint
|
||||
.. _AUTHORS: http://github.com/kennethreitz/clint/blob/master/AUTHORS
|
||||
.. _AUTHORS: http://github.com/kennethreitz/clint/blob/develop/AUTHORS
|
||||
|
||||
+10
-6
@@ -11,7 +11,14 @@ This module sets up the main interface for all of clint.
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
from . import arguments
|
||||
try:
|
||||
from collections import OrderedDict
|
||||
except ImportError:
|
||||
from .packages.ordereddict import OrderedDict
|
||||
import collections
|
||||
collections.OrderedDict = OrderedDict
|
||||
|
||||
from .arguments import *
|
||||
from . import textui
|
||||
from . import utils
|
||||
from .pipes import piped_in
|
||||
@@ -19,12 +26,9 @@ from .pipes import piped_in
|
||||
|
||||
|
||||
__title__ = 'clint'
|
||||
__version__ = '0.3.0'
|
||||
__build__ = 0x000300
|
||||
__version__ = '0.3.7'
|
||||
__build__ = 0x000307
|
||||
__author__ = 'Kenneth Reitz'
|
||||
__license__ = 'ISC'
|
||||
__copyright__ = 'Copyright 2012 Kenneth Reitz'
|
||||
__docformat__ = 'restructuredtext'
|
||||
|
||||
|
||||
args = arguments.Args()
|
||||
|
||||
+1
-1
@@ -241,7 +241,7 @@ class Args(object):
|
||||
for arg in self.all:
|
||||
if arg.startswith('-'):
|
||||
_current_group = arg
|
||||
collection[arg] = Args(no_argv=True)
|
||||
collection.setdefault(arg, Args(no_argv=True))
|
||||
else:
|
||||
if _current_group:
|
||||
collection[_current_group]._args.append(arg)
|
||||
|
||||
+4
-4
@@ -20,12 +20,12 @@ except NameError:
|
||||
unicode = str
|
||||
|
||||
|
||||
def join(l, conj=CONJUNCTION, im_a_moron=MORON_MODE, seperator=COMMA):
|
||||
def join(l, conj=CONJUNCTION, im_a_moron=MORON_MODE, separator=COMMA):
|
||||
"""Joins lists of words. Oxford comma and all."""
|
||||
|
||||
collector = []
|
||||
left = len(l)
|
||||
seperator = seperator + SPACE
|
||||
separator = separator + SPACE
|
||||
conj = conj + SPACE
|
||||
|
||||
for _l in l[:]:
|
||||
@@ -37,12 +37,12 @@ def join(l, conj=CONJUNCTION, im_a_moron=MORON_MODE, seperator=COMMA):
|
||||
if len(l) == 2 or im_a_moron:
|
||||
collector.append(SPACE)
|
||||
else:
|
||||
collector.append(seperator)
|
||||
collector.append(separator)
|
||||
|
||||
collector.append(conj)
|
||||
|
||||
elif left is not 0:
|
||||
collector.append(seperator)
|
||||
collector.append(separator)
|
||||
|
||||
return unicode(str().join(collector))
|
||||
|
||||
|
||||
@@ -7,9 +7,13 @@ clint.textui
|
||||
This module provides the text output helper system.
|
||||
|
||||
"""
|
||||
|
||||
import sys
|
||||
if sys.platform.startswith('win'):
|
||||
from ..packages import colorama
|
||||
colorama.init()
|
||||
|
||||
from . import colored
|
||||
from . import progress
|
||||
from . import prompt
|
||||
|
||||
from .core import *
|
||||
|
||||
+59
-28
@@ -11,6 +11,7 @@ This module provides a simple and elegant wrapper for colorama.
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
@@ -25,26 +26,53 @@ __all__ = (
|
||||
)
|
||||
|
||||
COLORS = __all__[:-2]
|
||||
DISABLE_COLOR = False
|
||||
|
||||
if not sys.stdout.isatty():
|
||||
if 'get_ipython' in dir():
|
||||
"""
|
||||
when ipython is fired lot of variables like _oh, etc are used.
|
||||
There are so many ways to find current python interpreter is ipython.
|
||||
get_ipython is easiest is most appealing for readers to understand.
|
||||
"""
|
||||
DISABLE_COLOR = True
|
||||
else:
|
||||
colorama.init(autoreset=True)
|
||||
DISABLE_COLOR = False
|
||||
|
||||
|
||||
class ColoredString(object):
|
||||
"""Enhanced string for __len__ operations on Colored output."""
|
||||
def __init__(self, color, s):
|
||||
def __init__(self, color, s, always_color=False, bold=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
|
||||
|
||||
@property
|
||||
def color_str(self):
|
||||
if sys.stdout.isatty() and not DISABLE_COLOR:
|
||||
return '%s%s%s' % (
|
||||
getattr(colorama.Fore, self.color), self.s, colorama.Fore.RESET)
|
||||
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'))
|
||||
|
||||
if self.always_color:
|
||||
return c
|
||||
elif sys.stdout.isatty() and not DISABLE_COLOR:
|
||||
return c
|
||||
else:
|
||||
return self.s
|
||||
|
||||
@@ -56,13 +84,19 @@ class ColoredString(object):
|
||||
return "<%s-string: '%s'>" % (self.color, self.s)
|
||||
|
||||
def __unicode__(self):
|
||||
return self.color_str
|
||||
value = self.color_str
|
||||
if isinstance(value, bytes):
|
||||
return value.decode('utf8')
|
||||
return value
|
||||
|
||||
if PY3:
|
||||
__str__ = __unicode__
|
||||
else:
|
||||
def __str__(self):
|
||||
return unicode(self).encode('utf8')
|
||||
value = self.color_str
|
||||
if isinstance(value, bytes):
|
||||
return value
|
||||
return value.encode('utf8')
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self.color_str)
|
||||
@@ -76,9 +110,6 @@ class ColoredString(object):
|
||||
def __mul__(self, other):
|
||||
return (self.color_str * other)
|
||||
|
||||
def split(self, sep=None):
|
||||
return [self._new(s) for s in self.s.split(sep)]
|
||||
|
||||
def _new(self, s):
|
||||
return ColoredString(self.color, s)
|
||||
|
||||
@@ -93,29 +124,29 @@ def clean(s):
|
||||
return txt
|
||||
|
||||
|
||||
def black(string):
|
||||
return ColoredString('BLACK', string)
|
||||
def black(string, always=False, bold=False):
|
||||
return ColoredString('BLACK', string, always_color=always, bold=bold)
|
||||
|
||||
def red(string):
|
||||
return ColoredString('RED', string)
|
||||
def red(string, always=False, bold=False):
|
||||
return ColoredString('RED', string, always_color=always, bold=bold)
|
||||
|
||||
def green(string):
|
||||
return ColoredString('GREEN', string)
|
||||
def green(string, always=False, bold=False):
|
||||
return ColoredString('GREEN', string, always_color=always, bold=bold)
|
||||
|
||||
def yellow(string):
|
||||
return ColoredString('YELLOW', string)
|
||||
def yellow(string, always=False, bold=False):
|
||||
return ColoredString('YELLOW', string, always_color=always, bold=bold)
|
||||
|
||||
def blue(string):
|
||||
return ColoredString('BLUE', string)
|
||||
def blue(string, always=False, bold=False):
|
||||
return ColoredString('BLUE', string, always_color=always, bold=bold)
|
||||
|
||||
def magenta(string):
|
||||
return ColoredString('MAGENTA', string)
|
||||
def magenta(string, always=False, bold=False):
|
||||
return ColoredString('MAGENTA', string, always_color=always, bold=bold)
|
||||
|
||||
def cyan(string):
|
||||
return ColoredString('CYAN', string)
|
||||
def cyan(string, always=False, bold=False):
|
||||
return ColoredString('CYAN', string, always_color=always, bold=bold)
|
||||
|
||||
def white(string):
|
||||
return ColoredString('WHITE', string)
|
||||
def white(string, always=False, bold=False):
|
||||
return ColoredString('WHITE', string, always_color=always, bold=bold)
|
||||
|
||||
def disable():
|
||||
"""Disables colors."""
|
||||
|
||||
+49
-54
@@ -13,12 +13,15 @@ from __future__ import absolute_import
|
||||
|
||||
import sys
|
||||
|
||||
from contextlib import contextmanager
|
||||
|
||||
from .formatters import max_width, min_width
|
||||
from .cols import columns
|
||||
from ..utils import tsplit
|
||||
|
||||
|
||||
__all__ = ('puts', 'puts_err', 'indent', 'columns', 'max_width', 'min_width')
|
||||
__all__ = ('puts', 'puts_err', 'indent', 'dedent', 'columns', 'max_width',
|
||||
'min_width', 'STDOUT', 'STDERR')
|
||||
|
||||
|
||||
STDOUT = sys.stdout.write
|
||||
@@ -26,68 +29,60 @@ STDERR = sys.stderr.write
|
||||
|
||||
NEWLINES = ('\n', '\r', '\r\n')
|
||||
|
||||
INDENT_STRINGS = []
|
||||
|
||||
# Private
|
||||
|
||||
class Writer(object):
|
||||
"""WriterUtilized by context managers."""
|
||||
|
||||
shared = dict(indent_level=0, indent_strings=[])
|
||||
|
||||
|
||||
def __init__(self, indent=0, quote='', indent_char=' '):
|
||||
self.indent = indent
|
||||
self.indent_char = indent_char
|
||||
self.indent_quote = quote
|
||||
if self.indent > 0:
|
||||
self.indent_string = ''.join((
|
||||
str(quote),
|
||||
(self.indent_char * (indent - len(self.indent_quote)))
|
||||
))
|
||||
else:
|
||||
self.indent_string = ''.join((
|
||||
('\x08' * (-1 * (indent - len(self.indent_quote)))),
|
||||
str(quote))
|
||||
)
|
||||
|
||||
if len(self.indent_string):
|
||||
self.shared['indent_strings'].append(self.indent_string)
|
||||
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
|
||||
def __exit__(self, type, value, traceback):
|
||||
self.shared['indent_strings'].pop()
|
||||
|
||||
|
||||
def __call__(self, s, newline=True, stream=STDOUT):
|
||||
|
||||
if newline:
|
||||
s = tsplit(s, NEWLINES)
|
||||
s = map(str, s)
|
||||
indent = ''.join(self.shared['indent_strings'])
|
||||
|
||||
s = (str('\n' + indent)).join(s)
|
||||
|
||||
_str = ''.join((
|
||||
''.join(self.shared['indent_strings']),
|
||||
str(s),
|
||||
'\n' if newline else ''
|
||||
def _indent(indent=0, quote='', indent_char=' '):
|
||||
"""Indent util function, compute new indent_string"""
|
||||
if indent > 0:
|
||||
indent_string = ''.join((
|
||||
str(quote),
|
||||
(indent_char * (indent - len(quote)))
|
||||
))
|
||||
stream(_str)
|
||||
else:
|
||||
indent_string = ''.join((
|
||||
('\x08' * (-1 * (indent - len(quote)))),
|
||||
str(quote))
|
||||
)
|
||||
|
||||
if len(indent_string):
|
||||
INDENT_STRINGS.append(indent_string)
|
||||
|
||||
# Public
|
||||
|
||||
def puts(s='', newline=True, stream=STDOUT):
|
||||
"""Prints given string to stdout via Writer interface."""
|
||||
Writer()(s, newline, stream=stream)
|
||||
"""Prints given string to stdout."""
|
||||
if newline:
|
||||
s = tsplit(s, NEWLINES)
|
||||
s = map(str, s)
|
||||
indent = ''.join(INDENT_STRINGS)
|
||||
|
||||
s = (str('\n' + indent)).join(s)
|
||||
|
||||
_str = ''.join((
|
||||
''.join(INDENT_STRINGS),
|
||||
str(s),
|
||||
'\n' if newline else ''
|
||||
))
|
||||
stream(_str)
|
||||
|
||||
def puts_err(s='', newline=True, stream=STDERR):
|
||||
"""Prints given string to stderr via Writer interface."""
|
||||
Writer()(s, newline, stream=stream)
|
||||
"""Prints given string to stderr."""
|
||||
puts(s, newline, stream)
|
||||
|
||||
def dedent():
|
||||
"""Dedent next strings, use only if you use indent otherwise than as a
|
||||
context."""
|
||||
INDENT_STRINGS.pop()
|
||||
|
||||
@contextmanager
|
||||
def _indent_context():
|
||||
"""Indentation context manager."""
|
||||
yield
|
||||
dedent()
|
||||
|
||||
def indent(indent=4, quote=''):
|
||||
"""Indentation context manager."""
|
||||
return Writer(indent=indent, quote=quote)
|
||||
"""Indentation manager, return an indentation context manager."""
|
||||
_indent(indent, quote)
|
||||
return _indent_context()
|
||||
|
||||
+125
-31
@@ -11,26 +11,142 @@ This module provides the progressbar functionality.
|
||||
from __future__ import absolute_import
|
||||
|
||||
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\r'
|
||||
BAR_TEMPLATE = '%s[%s%s] %i/%i - %s\r'
|
||||
MILL_TEMPLATE = '%s %s %i/%i\r'
|
||||
|
||||
DOTS_CHAR = '.'
|
||||
BAR_FILLED_CHAR = '#'
|
||||
BAR_EMPTY_CHAR = ' '
|
||||
MILL_CHARS = ['|', '/', '-', '\\']
|
||||
|
||||
def bar(it, label='', width=32, hide=False, empty_char=BAR_EMPTY_CHAR, filled_char=BAR_FILLED_CHAR):
|
||||
"""Progress iterator. Wrap your iterables with it."""
|
||||
#How long to wait before recalculating the ETA
|
||||
ETA_INTERVAL = 1
|
||||
#How many intervals (excluding the current one) to calculate the simple moving average
|
||||
ETA_SMA_WINDOW = 9
|
||||
|
||||
def _show(_i):
|
||||
x = int(width*_i/count)
|
||||
if not hide:
|
||||
STREAM.write(BAR_TEMPLATE % (
|
||||
label, filled_char*x, empty_char*(width-x), _i, count))
|
||||
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()
|
||||
|
||||
count = len(it)
|
||||
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:
|
||||
|
||||
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"""
|
||||
|
||||
count = 0
|
||||
|
||||
if not hide:
|
||||
STREAM.write(label)
|
||||
|
||||
for (i, item) in enumerate(it):
|
||||
if not hide:
|
||||
if (i % every)==0: # True every "every" updates
|
||||
STREAM.write(DOTS_CHAR)
|
||||
sys.stderr.flush()
|
||||
|
||||
count += 1
|
||||
|
||||
yield item
|
||||
|
||||
STREAM.write('\n')
|
||||
STREAM.flush()
|
||||
|
||||
|
||||
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:
|
||||
return ' '
|
||||
else:
|
||||
return MILL_CHARS[(_i / every) % len(MILL_CHARS)]
|
||||
|
||||
def _show(_i):
|
||||
if not hide:
|
||||
if ((_i % every)==0 or # True every "every" updates
|
||||
(_i == count)): # And when we're done
|
||||
|
||||
STREAM.write(MILL_TEMPLATE % (
|
||||
label, _mill_char(_i), _i, count))
|
||||
STREAM.flush()
|
||||
|
||||
count = len(it) if expected_size is None else expected_size
|
||||
|
||||
if count:
|
||||
_show(0)
|
||||
@@ -43,25 +159,3 @@ def bar(it, label='', width=32, hide=False, empty_char=BAR_EMPTY_CHAR, filled_ch
|
||||
if not hide:
|
||||
STREAM.write('\n')
|
||||
STREAM.flush()
|
||||
|
||||
|
||||
def dots(it, label='', hide=False):
|
||||
"""Progress iterator. Prints a dot for each item being iterated"""
|
||||
|
||||
count = 0
|
||||
|
||||
if not hide:
|
||||
STREAM.write(label)
|
||||
|
||||
for item in it:
|
||||
if not hide:
|
||||
STREAM.write(DOTS_CHAR)
|
||||
sys.stderr.flush()
|
||||
|
||||
count += 1
|
||||
|
||||
yield item
|
||||
|
||||
STREAM.write('\n')
|
||||
STREAM.flush()
|
||||
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
# -*- coding: utf8 -*-
|
||||
|
||||
"""
|
||||
clint.textui.prompt
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Module for simple interactive prompts handling
|
||||
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import, print_function
|
||||
|
||||
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 default not in ['y', 'n']:
|
||||
default = 'y'
|
||||
|
||||
# Let's build the prompt
|
||||
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
|
||||
# with default input
|
||||
if not batch:
|
||||
input = raw_input(prompt).strip()
|
||||
else:
|
||||
print(prompt)
|
||||
input = ''
|
||||
|
||||
# If input is empty default choice is assumed
|
||||
# so we return True
|
||||
if input == '':
|
||||
return True
|
||||
|
||||
# Given 'yes' as input if default choice is y
|
||||
# then return True, False otherwise
|
||||
if match('y(?:es)?', input, I):
|
||||
return True if default == 'y' else False
|
||||
|
||||
# Given 'no' as input if default choice is n
|
||||
# then return True, False otherwise
|
||||
elif match('n(?:o)?', input, I):
|
||||
return True if default == 'n' else False
|
||||
+7
-29
@@ -61,37 +61,15 @@ def mkdir_p(path):
|
||||
|
||||
def tsplit(string, delimiters):
|
||||
"""Behaves str.split but supports tuples of delimiters."""
|
||||
|
||||
delimiters = tuple(delimiters)
|
||||
stack = [string,]
|
||||
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)
|
||||
|
||||
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."""
|
||||
|
||||
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
|
||||
return [string[i:i+size] for i in range(0, len(string), size)]
|
||||
|
||||
Regular → Executable
+5
-2
@@ -6,9 +6,11 @@ import os
|
||||
|
||||
sys.path.insert(0, os.path.abspath('..'))
|
||||
|
||||
from clint import args
|
||||
from clint.arguments 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))
|
||||
@@ -16,4 +18,5 @@ with indent(4, quote='>>>'):
|
||||
puts(colored.red('NOT Files detected: ') + str(args.not_files))
|
||||
puts(colored.red('Grouped Arguments: ') + str(dict(args.grouped)))
|
||||
|
||||
print
|
||||
print
|
||||
|
||||
|
||||
Executable
+13
@@ -0,0 +1,13 @@
|
||||
#! /usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from clint.arguments import Args
|
||||
from clint.textui import puts, colored
|
||||
|
||||
all_args = Args().grouped
|
||||
|
||||
for item in all_args:
|
||||
if item is not '_':
|
||||
puts(colored.red("key:%s"%item))
|
||||
print(all_args[item].all)
|
||||
|
||||
Executable
+4
@@ -0,0 +1,4 @@
|
||||
echo "python get_each_args.py --name kracekumar --email me@kracekumar.com"
|
||||
python get_each_args.py --name kracekumar --email me@kracekumar.com
|
||||
echo "python get_each_args.py --languages python c html ruby --email me@kracekumar.com"
|
||||
python get_each_args.py --langauges python c html ruby --email me@kracekumar.com
|
||||
+15
-1
@@ -14,7 +14,21 @@ 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)
|
||||
|
||||
|
||||
for i in progress.mill(range(100)):
|
||||
sleep(random() * 0.2)
|
||||
|
||||
# Override the expected_size, for iterables that don't support len()
|
||||
D = dict(zip(range(100), range(100)))
|
||||
for k, v in progress.bar(D.iteritems(), expected_size=len(D)):
|
||||
sleep(random() * 0.2)
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"title": "Bashō's 'old pond'",
|
||||
"text": "古池や蛙飛込む水の音"
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
import sys
|
||||
import codecs
|
||||
|
||||
sys.path.insert(0, os.path.abspath('..'))
|
||||
|
||||
try:
|
||||
import json
|
||||
except:
|
||||
import simplejson as json
|
||||
|
||||
from clint.arguments import Args
|
||||
from clint import piped_in
|
||||
from clint.textui import colored, puts, indent
|
||||
|
||||
args = Args()
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
puts('Test:')
|
||||
with indent(4):
|
||||
puts('%s Fake test 1.' % colored.green('✔'))
|
||||
puts('%s Fake test 2.' % colored.red('✖'))
|
||||
|
||||
puts('')
|
||||
puts('Greet:')
|
||||
with indent(4):
|
||||
puts(colored.red('Здравствуйте'))
|
||||
puts(colored.green('你好。'))
|
||||
puts(colored.yellow('سلام'))
|
||||
puts(colored.magenta('안녕하세요'))
|
||||
puts(colored.blue('नमस्ते'))
|
||||
puts(colored.cyan('γειά σου'))
|
||||
|
||||
puts('')
|
||||
puts('Arguments:')
|
||||
with indent(4):
|
||||
puts('%s' % colored.red(args[0]))
|
||||
|
||||
puts('')
|
||||
puts('File:')
|
||||
with indent(4):
|
||||
f = args.files[0]
|
||||
puts(colored.yellow('%s:' % f))
|
||||
with indent(2):
|
||||
fd = codecs.open(f, encoding='utf-8')
|
||||
for line in fd:
|
||||
line = line.strip('\n\r')
|
||||
puts(colored.yellow(' %s' % line))
|
||||
fd.close()
|
||||
|
||||
puts('')
|
||||
puts('Input:')
|
||||
with indent(4):
|
||||
in_data = json.loads(piped_in())
|
||||
title = in_data['title']
|
||||
text = in_data['text']
|
||||
puts(colored.blue('Title: %s' % title))
|
||||
puts(colored.magenta('Text: %s' % text))
|
||||
Executable
+3
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
python unicode.py こんにちは。 unicode.json < unicode.json
|
||||
@@ -4,12 +4,13 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
from distutils.core import setup
|
||||
try:
|
||||
from setuptools import setup
|
||||
except ImportError:
|
||||
from distutils.core import setup
|
||||
|
||||
import clint
|
||||
|
||||
|
||||
|
||||
def publish():
|
||||
"""Publish to PyPi"""
|
||||
os.system("python setup.py sdist upload")
|
||||
@@ -18,7 +19,7 @@ if sys.argv[-1] == "publish":
|
||||
publish()
|
||||
sys.exit()
|
||||
|
||||
required = []
|
||||
required = ['args']
|
||||
|
||||
setup(
|
||||
name='clint',
|
||||
@@ -44,7 +45,6 @@ setup(
|
||||
'License :: OSI Approved :: ISC License (ISCL)',
|
||||
'Programming Language :: Python',
|
||||
'Programming Language :: Python :: 2',
|
||||
'Programming Language :: Python :: 2.5',
|
||||
'Programming Language :: Python :: 2.6',
|
||||
'Programming Language :: Python :: 2.7',
|
||||
'Programming Language :: Python :: 3',
|
||||
|
||||
+44
-2
@@ -3,11 +3,12 @@
|
||||
|
||||
"""Clint Test Suite."""
|
||||
|
||||
import os
|
||||
import unittest
|
||||
|
||||
|
||||
class TablibTestCase(unittest.TestCase):
|
||||
"""Tablib test cases."""
|
||||
class ClintTestCase(unittest.TestCase):
|
||||
"""Clint test cases."""
|
||||
|
||||
def setUp(self):
|
||||
import clint
|
||||
@@ -16,5 +17,46 @@ class TablibTestCase(unittest.TestCase):
|
||||
def tearDown(self):
|
||||
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")
|
||||
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()
|
||||
|
||||
Reference in New Issue
Block a user