login page

This commit is contained in:
Alicja Cięciwa
2020-10-27 12:57:58 +01:00
commit cb8886666c
8545 changed files with 1082463 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 Pavlo Dmytrenko
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from .__version__ import __version__ # noqa
from .api import kbi_safe_yaspin, yaspin
from .base_spinner import Spinner
__all__ = ("yaspin", "kbi_safe_yaspin", "Spinner")

View File

@@ -0,0 +1 @@
__version__ = "0.14.3"

View File

@@ -0,0 +1,90 @@
# -*- coding: utf-8 -*-
"""
yaspin.api
~~~~~~~~~~
This module implements the Yaspin API.
:copyright: (c) 2018 by Pavlo Dmytrenko.
:license: MIT, see LICENSE for more details.
"""
import signal
from .core import Yaspin
from .signal_handlers import default_handler
def yaspin(*args, **kwargs):
"""Display spinner in stdout.
Can be used as a context manager or as a function decorator.
Arguments:
spinner (base_spinner.Spinner, optional): Spinner object to use.
text (str, optional): Text to show along with spinner.
color (str, optional): Spinner color.
on_color (str, optional): Color highlight for the spinner.
attrs (list, optional): Color attributes for the spinner.
reversal (bool, optional): Reverse spin direction.
side (str, optional): Place spinner to the right or left end
of the text string.
sigmap (dict, optional): Maps POSIX signals to their respective
handlers.
Returns:
core.Yaspin: instance of the Yaspin class.
Raises:
ValueError: If unsupported ``color`` is specified.
ValueError: If unsupported ``on_color`` is specified.
ValueError: If unsupported color attribute in ``attrs``
is specified.
ValueError: If trying to register handler for SIGKILL signal.
ValueError: If unsupported ``side`` is specified.
Available text colors:
red, green, yellow, blue, magenta, cyan, white.
Available text highlights:
on_red, on_green, on_yellow, on_blue, on_magenta, on_cyan,
on_white, on_grey.
Available attributes:
bold, dark, underline, blink, reverse, concealed.
Example::
# Use as a context manager
with yaspin():
some_operations()
# Context manager with text
with yaspin(text="Processing..."):
some_operations()
# Context manager with custom sequence
with yaspin(Spinner('-\\|/', 150)):
some_operations()
# As decorator
@yaspin(text="Loading...")
def foo():
time.sleep(5)
foo()
"""
return Yaspin(*args, **kwargs)
def kbi_safe_yaspin(*args, **kwargs):
kwargs["sigmap"] = {signal.SIGINT: default_handler}
return Yaspin(*args, **kwargs)
# Handle PYTHONOPTIMIZE=2 case, when docstrings are set to None.
if yaspin.__doc__:
_kbi_safe_doc = yaspin.__doc__.replace("yaspin", "kbi_safe_yaspin")
kbi_safe_yaspin.__doc__ = _kbi_safe_doc

View File

@@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
"""
yaspin.base_spinner
~~~~~~~~~~~~~~~~~~~
Spinner class, used to construct other spinners.
"""
from __future__ import absolute_import
from collections import namedtuple
Spinner = namedtuple("Spinner", "frames interval")
default_spinner = Spinner("⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏", 80)

View File

@@ -0,0 +1,33 @@
# -*- coding: utf-8 -*-
"""
yaspin.compat
~~~~~~~~~~~~~
Compatibility layer.
"""
import sys
PY2 = sys.version_info[0] == 2
if PY2:
builtin_str = str
bytes = str
str = unicode # noqa
basestring = basestring # noqa
def iteritems(dct):
return dct.iteritems()
else:
builtin_str = str
bytes = bytes
str = str
basestring = (str, bytes)
def iteritems(dct):
return dct.items()

View File

@@ -0,0 +1,110 @@
# -*- coding: utf-8 -*-
"""
yaspin.constants
~~~~~~~~~~~~~~~~
Some setups.
"""
ENCODING = "utf-8"
COLOR_MAP = {
# name: type
"blink": "attrs",
"bold": "attrs",
"concealed": "attrs",
"dark": "attrs",
"reverse": "attrs",
"underline": "attrs",
"blue": "color",
"cyan": "color",
"green": "color",
"magenta": "color",
"red": "color",
"white": "color",
"yellow": "color",
"on_blue": "on_color",
"on_cyan": "on_color",
"on_green": "on_color",
"on_grey": "on_color",
"on_magenta": "on_color",
"on_red": "on_color",
"on_white": "on_color",
"on_yellow": "on_color",
}
COLOR_ATTRS = COLOR_MAP.keys()
# Get spinner names:
# $ < yaspin/data/spinners.json | jq '. | keys'
SPINNER_ATTRS = [
"arc",
"arrow",
"arrow2",
"arrow3",
"balloon",
"balloon2",
"bounce",
"bouncingBall",
"bouncingBar",
"boxBounce",
"boxBounce2",
"christmas",
"circle",
"circleHalves",
"circleQuarters",
"clock",
"dots",
"dots10",
"dots11",
"dots12",
"dots2",
"dots3",
"dots4",
"dots5",
"dots6",
"dots7",
"dots8",
"dots9",
"dqpb",
"earth",
"flip",
"grenade",
"growHorizontal",
"growVertical",
"hamburger",
"hearts",
"layer",
"line",
"line2",
"monkey",
"moon",
"noise",
"pipe",
"point",
"pong",
"runner",
"shark",
"simpleDots",
"simpleDotsScrolling",
"smiley",
"squareCorners",
"squish",
"star",
"star2",
"toggle",
"toggle10",
"toggle11",
"toggle12",
"toggle13",
"toggle2",
"toggle3",
"toggle4",
"toggle5",
"toggle6",
"toggle7",
"toggle8",
"toggle9",
"triangle",
"weather",
]

View File

@@ -0,0 +1,547 @@
# -*- coding: utf-8 -*-
"""
yaspin.yaspin
~~~~~~~~~~~~~
A lightweight terminal spinner.
"""
from __future__ import absolute_import
import functools
import itertools
import signal
import sys
import threading
import time
import colorama
from pipenv.vendor.vistir import cursor
from .base_spinner import default_spinner
from .compat import PY2, basestring, builtin_str, bytes, iteritems, str
from .constants import COLOR_ATTRS, COLOR_MAP, ENCODING, SPINNER_ATTRS
from .helpers import to_unicode
from .termcolor import colored
colorama.init()
class Yaspin(object):
"""Implements a context manager that spawns a thread
to write spinner frames into a tty (stdout) during
context execution.
"""
# When Python finds its output attached to a terminal,
# it sets the sys.stdout.encoding attribute to the terminal's encoding.
# The print statement's handler will automatically encode unicode
# arguments into bytes.
#
# In Py2 when piping or redirecting output, Python does not detect
# the desired character set of the output, it sets sys.stdout.encoding
# to None, and print will invoke the default "ascii" codec.
#
# Py3 invokes "UTF-8" codec by default.
#
# Thats why in Py2, output should be encoded manually with desired
# encoding in order to support pipes and redirects.
def __init__(
self,
spinner=None,
text="",
color=None,
on_color=None,
attrs=None,
reversal=False,
side="left",
sigmap=None,
):
# Spinner
self._spinner = self._set_spinner(spinner)
self._frames = self._set_frames(self._spinner, reversal)
self._interval = self._set_interval(self._spinner)
self._cycle = self._set_cycle(self._frames)
# Color Specification
self._color = self._set_color(color) if color else color
self._on_color = self._set_on_color(on_color) if on_color else on_color
self._attrs = self._set_attrs(attrs) if attrs else set()
self._color_func = self._compose_color_func()
# Other
self._text = self._set_text(text)
self._side = self._set_side(side)
self._reversal = reversal
# Helper flags
self._stop_spin = None
self._hide_spin = None
self._spin_thread = None
self._last_frame = None
self._stdout_lock = threading.Lock()
# Signals
# In Python 2 signal.SIG* are of type int.
# In Python 3 signal.SIG* are enums.
#
# Signal = Union[enum.Enum, int]
# SigHandler = Union[enum.Enum, Callable]
self._sigmap = sigmap if sigmap else {} # Dict[Signal, SigHandler]
# Maps signals to their default handlers in order to reset
# custom handlers set by ``sigmap`` at the cleanup phase.
self._dfl_sigmap = {} # Dict[Signal, SigHandler]
#
# Dunders
#
def __repr__(self):
repr_ = u"<Yaspin frames={0!s}>".format(self._frames)
if PY2:
return repr_.encode(ENCODING)
return repr_
def __enter__(self):
self.start()
return self
def __exit__(self, exc_type, exc_val, traceback):
# Avoid stop() execution for the 2nd time
if self._spin_thread.is_alive():
self.stop()
return False # nothing is handled
def __call__(self, fn):
@functools.wraps(fn)
def inner(*args, **kwargs):
with self:
return fn(*args, **kwargs)
return inner
def __getattr__(self, name):
# CLI spinners
if name in SPINNER_ATTRS:
from .spinners import Spinners
sp = getattr(Spinners, name)
self.spinner = sp
# Color Attributes: "color", "on_color", "attrs"
elif name in COLOR_ATTRS:
attr_type = COLOR_MAP[name]
# Call appropriate property setters;
# _color_func is updated automatically by setters.
if attr_type == "attrs":
self.attrs = [name] # calls property setter
if attr_type in ("color", "on_color"):
setattr(self, attr_type, name) # calls property setter
# Side: "left" or "right"
elif name in ("left", "right"):
self.side = name # calls property setter
# Common error for unsupported attributes
else:
raise AttributeError(
"'{0}' object has no attribute: '{1}'".format(
self.__class__.__name__, name
)
)
return self
#
# Properties
#
@property
def spinner(self):
return self._spinner
@spinner.setter
def spinner(self, sp):
self._spinner = self._set_spinner(sp)
self._frames = self._set_frames(self._spinner, self._reversal)
self._interval = self._set_interval(self._spinner)
self._cycle = self._set_cycle(self._frames)
@property
def text(self):
return self._text
@text.setter
def text(self, txt):
self._text = self._set_text(txt)
@property
def color(self):
return self._color
@color.setter
def color(self, value):
self._color = self._set_color(value) if value else value
self._color_func = self._compose_color_func() # update
@property
def on_color(self):
return self._on_color
@on_color.setter
def on_color(self, value):
self._on_color = self._set_on_color(value) if value else value
self._color_func = self._compose_color_func() # update
@property
def attrs(self):
return list(self._attrs)
@attrs.setter
def attrs(self, value):
new_attrs = self._set_attrs(value) if value else set()
self._attrs = self._attrs.union(new_attrs)
self._color_func = self._compose_color_func() # update
@property
def side(self):
return self._side
@side.setter
def side(self, value):
self._side = self._set_side(value)
@property
def reversal(self):
return self._reversal
@reversal.setter
def reversal(self, value):
self._reversal = value
self._frames = self._set_frames(self._spinner, self._reversal)
self._cycle = self._set_cycle(self._frames)
#
# Public
#
def start(self):
if self._sigmap:
self._register_signal_handlers()
if sys.stdout.isatty():
self._hide_cursor()
self._stop_spin = threading.Event()
self._hide_spin = threading.Event()
self._spin_thread = threading.Thread(target=self._spin)
self._spin_thread.start()
def stop(self):
if self._dfl_sigmap:
# Reset registered signal handlers to default ones
self._reset_signal_handlers()
if self._spin_thread:
self._stop_spin.set()
self._spin_thread.join()
sys.stdout.write("\r")
self._clear_line()
if sys.stdout.isatty():
self._show_cursor()
def hide(self):
"""Hide the spinner to allow for custom writing to the terminal."""
thr_is_alive = self._spin_thread and self._spin_thread.is_alive()
if thr_is_alive and not self._hide_spin.is_set():
with self._stdout_lock:
# set the hidden spinner flag
self._hide_spin.set()
# clear the current line
sys.stdout.write("\r")
self._clear_line()
# flush the stdout buffer so the current line
# can be rewritten to
sys.stdout.flush()
def show(self):
"""Show the hidden spinner."""
thr_is_alive = self._spin_thread and self._spin_thread.is_alive()
if thr_is_alive and self._hide_spin.is_set():
with self._stdout_lock:
# clear the hidden spinner flag
self._hide_spin.clear()
# clear the current line so the spinner is not appended to it
sys.stdout.write("\r")
self._clear_line()
def write(self, text):
"""Write text in the terminal without breaking the spinner."""
# similar to tqdm.write()
# https://pypi.python.org/pypi/tqdm#writing-messages
with self._stdout_lock:
sys.stdout.write("\r")
self._clear_line()
_text = to_unicode(text)
if PY2:
_text = _text.encode(ENCODING)
# Ensure output is bytes for Py2 and Unicode for Py3
assert isinstance(_text, builtin_str)
sys.stdout.write("{0}\n".format(_text))
def ok(self, text="OK"):
"""Set Ok (success) finalizer to a spinner."""
_text = text if text else "OK"
self._freeze(_text)
def fail(self, text="FAIL"):
"""Set fail finalizer to a spinner."""
_text = text if text else "FAIL"
self._freeze(_text)
#
# Protected
#
def _freeze(self, final_text):
"""Stop spinner, compose last frame and 'freeze' it."""
text = to_unicode(final_text)
self._last_frame = self._compose_out(text, mode="last")
# Should be stopped here, otherwise prints after
# self._freeze call will mess up the spinner
self.stop()
with self._stdout_lock:
sys.stdout.write(self._last_frame)
def _spin(self):
while not self._stop_spin.is_set():
if self._hide_spin.is_set():
# Wait a bit to avoid wasting cycles
time.sleep(self._interval)
continue
# Compose output
spin_phase = next(self._cycle)
out = self._compose_out(spin_phase)
# Write
with self._stdout_lock:
sys.stdout.write(out)
self._clear_line()
sys.stdout.flush()
# Wait
time.sleep(self._interval)
def _compose_color_func(self):
fn = functools.partial(
colored,
color=self._color,
on_color=self._on_color,
attrs=list(self._attrs),
)
return fn
def _compose_out(self, frame, mode=None):
# Ensure Unicode input
assert isinstance(frame, str)
assert isinstance(self._text, str)
frame = frame.encode(ENCODING) if PY2 else frame
text = self._text.encode(ENCODING) if PY2 else self._text
# Colors
if self._color_func is not None:
frame = self._color_func(frame)
# Position
if self._side == "right":
frame, text = text, frame
# Mode
if not mode:
out = "\r{0} {1}".format(frame, text)
else:
out = "{0} {1}\n".format(frame, text)
# Ensure output is bytes for Py2 and Unicode for Py3
assert isinstance(out, builtin_str)
return out
def _register_signal_handlers(self):
# SIGKILL cannot be caught or ignored, and the receiving
# process cannot perform any clean-up upon receiving this
# signal.
try:
if signal.SIGKILL in self._sigmap.keys():
raise ValueError(
"Trying to set handler for SIGKILL signal. "
"SIGKILL cannot be cought or ignored in POSIX systems."
)
except AttributeError:
pass
for sig, sig_handler in iteritems(self._sigmap):
# A handler for a particular signal, once set, remains
# installed until it is explicitly reset. Store default
# signal handlers for subsequent reset at cleanup phase.
dfl_handler = signal.getsignal(sig)
self._dfl_sigmap[sig] = dfl_handler
# ``signal.SIG_DFL`` and ``signal.SIG_IGN`` are also valid
# signal handlers and are not callables.
if callable(sig_handler):
# ``signal.signal`` accepts handler function which is
# called with two arguments: signal number and the
# interrupted stack frame. ``functools.partial`` solves
# the problem of passing spinner instance into the handler
# function.
sig_handler = functools.partial(sig_handler, spinner=self)
signal.signal(sig, sig_handler)
def _reset_signal_handlers(self):
for sig, sig_handler in iteritems(self._dfl_sigmap):
signal.signal(sig, sig_handler)
#
# Static
#
@staticmethod
def _set_color(value):
# type: (str) -> str
available_values = [k for k, v in iteritems(COLOR_MAP) if v == "color"]
if value not in available_values:
raise ValueError(
"'{0}': unsupported color value. Use one of the: {1}".format(
value, ", ".join(available_values)
)
)
return value
@staticmethod
def _set_on_color(value):
# type: (str) -> str
available_values = [
k for k, v in iteritems(COLOR_MAP) if v == "on_color"
]
if value not in available_values:
raise ValueError(
"'{0}': unsupported on_color value. "
"Use one of the: {1}".format(
value, ", ".join(available_values)
)
)
return value
@staticmethod
def _set_attrs(attrs):
# type: (List[str]) -> Set[str]
available_values = [k for k, v in iteritems(COLOR_MAP) if v == "attrs"]
for attr in attrs:
if attr not in available_values:
raise ValueError(
"'{0}': unsupported attribute value. "
"Use one of the: {1}".format(
attr, ", ".join(available_values)
)
)
return set(attrs)
@staticmethod
def _set_spinner(spinner):
if not spinner:
sp = default_spinner
if hasattr(spinner, "frames") and hasattr(spinner, "interval"):
if not spinner.frames or not spinner.interval:
sp = default_spinner
else:
sp = spinner
else:
sp = default_spinner
return sp
@staticmethod
def _set_side(side):
# type: (str) -> str
if side not in ("left", "right"):
raise ValueError(
"'{0}': unsupported side value. "
"Use either 'left' or 'right'."
)
return side
@staticmethod
def _set_frames(spinner, reversal):
# type: (base_spinner.Spinner, bool) -> Union[str, List]
uframes = None # unicode frames
uframes_seq = None # sequence of unicode frames
if isinstance(spinner.frames, basestring):
uframes = to_unicode(spinner.frames) if PY2 else spinner.frames
# TODO (pavdmyt): support any type that implements iterable
if isinstance(spinner.frames, (list, tuple)):
# Empty ``spinner.frames`` is handled by ``Yaspin._set_spinner``
if spinner.frames and isinstance(spinner.frames[0], bytes):
uframes_seq = [to_unicode(frame) for frame in spinner.frames]
else:
uframes_seq = spinner.frames
_frames = uframes or uframes_seq
if not _frames:
# Empty ``spinner.frames`` is handled by ``Yaspin._set_spinner``.
# This code is very unlikely to be executed. However, it's still
# here to be on a safe side.
raise ValueError(
"{0!r}: no frames found in spinner".format(spinner)
)
# Builtin ``reversed`` returns reverse iterator,
# which adds unnecessary difficulty for returning
# unicode value;
# Hence using [::-1] syntax
frames = _frames[::-1] if reversal else _frames
return frames
@staticmethod
def _set_interval(spinner):
# Milliseconds to Seconds
return spinner.interval * 0.001
@staticmethod
def _set_cycle(frames):
return itertools.cycle(frames)
@staticmethod
def _set_text(text):
if PY2:
return to_unicode(text)
return text
@staticmethod
def _hide_cursor():
cursor.hide_cursor()
@staticmethod
def _show_cursor():
cursor.show_cursor()
@staticmethod
def _clear_line():
sys.stdout.write(chr(27) + "[K")

View File

@@ -0,0 +1,912 @@
{
"dots": {
"interval": 80,
"frames": [
"⠋",
"⠙",
"⠹",
"⠸",
"⠼",
"⠴",
"⠦",
"⠧",
"⠇",
"⠏"
]
},
"dots2": {
"interval": 80,
"frames": [
"⣾",
"⣽",
"⣻",
"⢿",
"⡿",
"⣟",
"⣯",
"⣷"
]
},
"dots3": {
"interval": 80,
"frames": [
"⠋",
"⠙",
"⠚",
"⠞",
"⠖",
"⠦",
"⠴",
"⠲",
"⠳",
"⠓"
]
},
"dots4": {
"interval": 80,
"frames": [
"⠄",
"⠆",
"⠇",
"⠋",
"⠙",
"⠸",
"⠰",
"⠠",
"⠰",
"⠸",
"⠙",
"⠋",
"⠇",
"⠆"
]
},
"dots5": {
"interval": 80,
"frames": [
"⠋",
"⠙",
"⠚",
"⠒",
"⠂",
"⠂",
"⠒",
"⠲",
"⠴",
"⠦",
"⠖",
"⠒",
"⠐",
"⠐",
"⠒",
"⠓",
"⠋"
]
},
"dots6": {
"interval": 80,
"frames": [
"⠁",
"⠉",
"⠙",
"⠚",
"⠒",
"⠂",
"⠂",
"⠒",
"⠲",
"⠴",
"⠤",
"⠄",
"⠄",
"⠤",
"⠴",
"⠲",
"⠒",
"⠂",
"⠂",
"⠒",
"⠚",
"⠙",
"⠉",
"⠁"
]
},
"dots7": {
"interval": 80,
"frames": [
"⠈",
"⠉",
"⠋",
"⠓",
"⠒",
"⠐",
"⠐",
"⠒",
"⠖",
"⠦",
"⠤",
"⠠",
"⠠",
"⠤",
"⠦",
"⠖",
"⠒",
"⠐",
"⠐",
"⠒",
"⠓",
"⠋",
"⠉",
"⠈"
]
},
"dots8": {
"interval": 80,
"frames": [
"⠁",
"⠁",
"⠉",
"⠙",
"⠚",
"⠒",
"⠂",
"⠂",
"⠒",
"⠲",
"⠴",
"⠤",
"⠄",
"⠄",
"⠤",
"⠠",
"⠠",
"⠤",
"⠦",
"⠖",
"⠒",
"⠐",
"⠐",
"⠒",
"⠓",
"⠋",
"⠉",
"⠈",
"⠈"
]
},
"dots9": {
"interval": 80,
"frames": [
"⢹",
"⢺",
"⢼",
"⣸",
"⣇",
"⡧",
"⡗",
"⡏"
]
},
"dots10": {
"interval": 80,
"frames": [
"⢄",
"⢂",
"⢁",
"⡁",
"⡈",
"⡐",
"⡠"
]
},
"dots11": {
"interval": 100,
"frames": [
"⠁",
"⠂",
"⠄",
"⡀",
"⢀",
"⠠",
"⠐",
"⠈"
]
},
"dots12": {
"interval": 80,
"frames": [
"⢀⠀",
"⡀⠀",
"⠄⠀",
"⢂⠀",
"⡂⠀",
"⠅⠀",
"⢃⠀",
"⡃⠀",
"⠍⠀",
"⢋⠀",
"⡋⠀",
"⠍⠁",
"⢋⠁",
"⡋⠁",
"⠍⠉",
"⠋⠉",
"⠋⠉",
"⠉⠙",
"⠉⠙",
"⠉⠩",
"⠈⢙",
"⠈⡙",
"⢈⠩",
"⡀⢙",
"⠄⡙",
"⢂⠩",
"⡂⢘",
"⠅⡘",
"⢃⠨",
"⡃⢐",
"⠍⡐",
"⢋⠠",
"⡋⢀",
"⠍⡁",
"⢋⠁",
"⡋⠁",
"⠍⠉",
"⠋⠉",
"⠋⠉",
"⠉⠙",
"⠉⠙",
"⠉⠩",
"⠈⢙",
"⠈⡙",
"⠈⠩",
"⠀⢙",
"⠀⡙",
"⠀⠩",
"⠀⢘",
"⠀⡘",
"⠀⠨",
"⠀⢐",
"⠀⡐",
"⠀⠠",
"⠀⢀",
"⠀⡀"
]
},
"line": {
"interval": 130,
"frames": [
"-",
"\\",
"|",
"/"
]
},
"line2": {
"interval": 100,
"frames": [
"⠂",
"-",
"",
"—",
"",
"-"
]
},
"pipe": {
"interval": 100,
"frames": [
"┤",
"┘",
"┴",
"└",
"├",
"┌",
"┬",
"┐"
]
},
"simpleDots": {
"interval": 400,
"frames": [
". ",
".. ",
"...",
" "
]
},
"simpleDotsScrolling": {
"interval": 200,
"frames": [
". ",
".. ",
"...",
" ..",
" .",
" "
]
},
"star": {
"interval": 70,
"frames": [
"✶",
"✸",
"✹",
"✺",
"✹",
"✷"
]
},
"star2": {
"interval": 80,
"frames": [
"+",
"x",
"*"
]
},
"flip": {
"interval": 70,
"frames": [
"_",
"_",
"_",
"-",
"`",
"`",
"'",
"´",
"-",
"_",
"_",
"_"
]
},
"hamburger": {
"interval": 100,
"frames": [
"☱",
"☲",
"☴"
]
},
"growVertical": {
"interval": 120,
"frames": [
"▁",
"▃",
"▄",
"▅",
"▆",
"▇",
"▆",
"▅",
"▄",
"▃"
]
},
"growHorizontal": {
"interval": 120,
"frames": [
"▏",
"▎",
"▍",
"▌",
"▋",
"▊",
"▉",
"▊",
"▋",
"▌",
"▍",
"▎"
]
},
"balloon": {
"interval": 140,
"frames": [
" ",
".",
"o",
"O",
"@",
"*",
" "
]
},
"balloon2": {
"interval": 120,
"frames": [
".",
"o",
"O",
"°",
"O",
"o",
"."
]
},
"noise": {
"interval": 100,
"frames": [
"▓",
"▒",
"░"
]
},
"bounce": {
"interval": 120,
"frames": [
"⠁",
"⠂",
"⠄",
"⠂"
]
},
"boxBounce": {
"interval": 120,
"frames": [
"▖",
"▘",
"▝",
"▗"
]
},
"boxBounce2": {
"interval": 100,
"frames": [
"▌",
"▀",
"▐",
"▄"
]
},
"triangle": {
"interval": 50,
"frames": [
"◢",
"◣",
"◤",
"◥"
]
},
"arc": {
"interval": 100,
"frames": [
"◜",
"◠",
"◝",
"◞",
"◡",
"◟"
]
},
"circle": {
"interval": 120,
"frames": [
"◡",
"⊙",
"◠"
]
},
"squareCorners": {
"interval": 180,
"frames": [
"◰",
"◳",
"◲",
"◱"
]
},
"circleQuarters": {
"interval": 120,
"frames": [
"◴",
"◷",
"◶",
"◵"
]
},
"circleHalves": {
"interval": 50,
"frames": [
"◐",
"◓",
"◑",
"◒"
]
},
"squish": {
"interval": 100,
"frames": [
"╫",
"╪"
]
},
"toggle": {
"interval": 250,
"frames": [
"⊶",
"⊷"
]
},
"toggle2": {
"interval": 80,
"frames": [
"▫",
"▪"
]
},
"toggle3": {
"interval": 120,
"frames": [
"□",
"■"
]
},
"toggle4": {
"interval": 100,
"frames": [
"■",
"□",
"▪",
"▫"
]
},
"toggle5": {
"interval": 100,
"frames": [
"▮",
"▯"
]
},
"toggle6": {
"interval": 300,
"frames": [
"",
""
]
},
"toggle7": {
"interval": 80,
"frames": [
"⦾",
"⦿"
]
},
"toggle8": {
"interval": 100,
"frames": [
"◍",
"◌"
]
},
"toggle9": {
"interval": 100,
"frames": [
"◉",
"◎"
]
},
"toggle10": {
"interval": 100,
"frames": [
"㊂",
"㊀",
"㊁"
]
},
"toggle11": {
"interval": 50,
"frames": [
"⧇",
"⧆"
]
},
"toggle12": {
"interval": 120,
"frames": [
"☗",
"☖"
]
},
"toggle13": {
"interval": 80,
"frames": [
"=",
"*",
"-"
]
},
"arrow": {
"interval": 100,
"frames": [
"←",
"↖",
"↑",
"↗",
"→",
"↘",
"↓",
"↙"
]
},
"arrow2": {
"interval": 80,
"frames": [
"⬆️ ",
"↗️ ",
"➡️ ",
"↘️ ",
"⬇️ ",
"↙️ ",
"⬅️ ",
"↖️ "
]
},
"arrow3": {
"interval": 120,
"frames": [
"▹▹▹▹▹",
"▸▹▹▹▹",
"▹▸▹▹▹",
"▹▹▸▹▹",
"▹▹▹▸▹",
"▹▹▹▹▸"
]
},
"bouncingBar": {
"interval": 80,
"frames": [
"[ ]",
"[= ]",
"[== ]",
"[=== ]",
"[ ===]",
"[ ==]",
"[ =]",
"[ ]",
"[ =]",
"[ ==]",
"[ ===]",
"[====]",
"[=== ]",
"[== ]",
"[= ]"
]
},
"bouncingBall": {
"interval": 80,
"frames": [
"( ● )",
"( ● )",
"( ● )",
"( ● )",
"( ●)",
"( ● )",
"( ● )",
"( ● )",
"( ● )",
"(● )"
]
},
"smiley": {
"interval": 200,
"frames": [
"😄 ",
"😝 "
]
},
"monkey": {
"interval": 300,
"frames": [
"🙈 ",
"🙈 ",
"🙉 ",
"🙊 "
]
},
"hearts": {
"interval": 100,
"frames": [
"💛 ",
"💙 ",
"💜 ",
"💚 ",
"❤️ "
]
},
"clock": {
"interval": 100,
"frames": [
"🕛 ",
"🕐 ",
"🕑 ",
"🕒 ",
"🕓 ",
"🕔 ",
"🕕 ",
"🕖 ",
"🕗 ",
"🕘 ",
"🕙 ",
"🕚 "
]
},
"earth": {
"interval": 180,
"frames": [
"🌍 ",
"🌎 ",
"🌏 "
]
},
"moon": {
"interval": 80,
"frames": [
"🌑 ",
"🌒 ",
"🌓 ",
"🌔 ",
"🌕 ",
"🌖 ",
"🌗 ",
"🌘 "
]
},
"runner": {
"interval": 140,
"frames": [
"🚶 ",
"🏃 "
]
},
"pong": {
"interval": 80,
"frames": [
"▐⠂ ▌",
"▐⠈ ▌",
"▐ ⠂ ▌",
"▐ ⠠ ▌",
"▐ ⡀ ▌",
"▐ ⠠ ▌",
"▐ ⠂ ▌",
"▐ ⠈ ▌",
"▐ ⠂ ▌",
"▐ ⠠ ▌",
"▐ ⡀ ▌",
"▐ ⠠ ▌",
"▐ ⠂ ▌",
"▐ ⠈ ▌",
"▐ ⠂▌",
"▐ ⠠▌",
"▐ ⡀▌",
"▐ ⠠ ▌",
"▐ ⠂ ▌",
"▐ ⠈ ▌",
"▐ ⠂ ▌",
"▐ ⠠ ▌",
"▐ ⡀ ▌",
"▐ ⠠ ▌",
"▐ ⠂ ▌",
"▐ ⠈ ▌",
"▐ ⠂ ▌",
"▐ ⠠ ▌",
"▐ ⡀ ▌",
"▐⠠ ▌"
]
},
"shark": {
"interval": 120,
"frames": [
"▐|\\____________▌",
"▐_|\\___________▌",
"▐__|\\__________▌",
"▐___|\\_________▌",
"▐____|\\________▌",
"▐_____|\\_______▌",
"▐______|\\______▌",
"▐_______|\\_____▌",
"▐________|\\____▌",
"▐_________|\\___▌",
"▐__________|\\__▌",
"▐___________|\\_▌",
"▐____________|\\▌",
"▐____________/|▌",
"▐___________/|_▌",
"▐__________/|__▌",
"▐_________/|___▌",
"▐________/|____▌",
"▐_______/|_____▌",
"▐______/|______▌",
"▐_____/|_______▌",
"▐____/|________▌",
"▐___/|_________▌",
"▐__/|__________▌",
"▐_/|___________▌",
"▐/|____________▌"
]
},
"dqpb": {
"interval": 100,
"frames": [
"d",
"q",
"p",
"b"
]
},
"weather": {
"interval": 100,
"frames": [
"☀️ ",
"☀️ ",
"☀️ ",
"🌤 ",
"⛅️ ",
"🌥 ",
"☁️ ",
"🌧 ",
"🌨 ",
"🌧 ",
"🌨 ",
"🌧 ",
"🌨 ",
"⛈ ",
"🌨 ",
"🌧 ",
"🌨 ",
"☁️ ",
"🌥 ",
"⛅️ ",
"🌤 ",
"☀️ ",
"☀️ "
]
},
"christmas": {
"interval": 400,
"frames": [
"🌲",
"🎄"
]
},
"grenade": {
"interval": 80,
"frames": [
"، ",
" ",
" ´ ",
" ‾ ",
" ⸌",
" ⸊",
" |",
" ",
" ⁕",
" ෴ ",
" ",
" ",
" ",
" "
]
},
"point": {
"interval": 125,
"frames": [
"∙∙∙",
"●∙∙",
"∙●∙",
"∙∙●",
"∙∙∙"
]
},
"layer": {
"interval": 150,
"frames": [
"-",
"=",
"≡"
]
}
}

View File

@@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
"""
yaspin.helpers
~~~~~~~~~~~~~~
Helper functions.
"""
from __future__ import absolute_import
from .compat import bytes
from .constants import ENCODING
def to_unicode(text_type, encoding=ENCODING):
if isinstance(text_type, bytes):
return text_type.decode(encoding)
return text_type

View File

@@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
"""
yaspin.signal_handlers
~~~~~~~~~~~~~~~~~~~~~~
Callback functions or "signal handlers", that are invoked
when the signal occurs.
"""
import sys
def default_handler(signum, frame, spinner):
"""Signal handler, used to gracefully shut down the ``spinner`` instance
when specified signal is received by the process running the ``spinner``.
``signum`` and ``frame`` are mandatory arguments. Check ``signal.signal``
function for more details.
"""
spinner.fail()
spinner.stop()
sys.exit(0)
def fancy_handler(signum, frame, spinner):
"""Signal handler, used to gracefully shut down the ``spinner`` instance
when specified signal is received by the process running the ``spinner``.
``signum`` and ``frame`` are mandatory arguments. Check ``signal.signal``
function for more details.
"""
spinner.red.fail("")
spinner.stop()
sys.exit(0)

View File

@@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
"""
yaspin.spinners
~~~~~~~~~~~~~~~
A collection of cli spinners.
"""
import codecs
import os
from collections import namedtuple
import json
THIS_DIR = os.path.dirname(os.path.realpath(__file__))
SPINNERS_PATH = os.path.join(THIS_DIR, "data/spinners.json")
def _hook(dct):
return namedtuple("Spinner", dct.keys())(*dct.values())
with codecs.open(SPINNERS_PATH, encoding="utf-8") as f:
Spinners = json.load(f, object_hook=_hook)

View File

@@ -0,0 +1,168 @@
# coding: utf-8
# Copyright (c) 2008-2011 Volvox Development Team
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
# Author: Konstantin Lepa <konstantin.lepa@gmail.com>
"""ANSII Color formatting for output in terminal."""
from __future__ import print_function
import os
__ALL__ = [ 'colored', 'cprint' ]
VERSION = (1, 1, 0)
ATTRIBUTES = dict(
list(zip([
'bold',
'dark',
'',
'underline',
'blink',
'',
'reverse',
'concealed'
],
list(range(1, 9))
))
)
del ATTRIBUTES['']
HIGHLIGHTS = dict(
list(zip([
'on_grey',
'on_red',
'on_green',
'on_yellow',
'on_blue',
'on_magenta',
'on_cyan',
'on_white'
],
list(range(40, 48))
))
)
COLORS = dict(
list(zip([
'grey',
'red',
'green',
'yellow',
'blue',
'magenta',
'cyan',
'white',
],
list(range(30, 38))
))
)
RESET = '\033[0m'
def colored(text, color=None, on_color=None, attrs=None):
"""Colorize text.
Available text colors:
red, green, yellow, blue, magenta, cyan, white.
Available text highlights:
on_red, on_green, on_yellow, on_blue, on_magenta, on_cyan, on_white.
Available attributes:
bold, dark, underline, blink, reverse, concealed.
Example:
colored('Hello, World!', 'red', 'on_grey', ['blue', 'blink'])
colored('Hello, World!', 'green')
"""
if os.getenv('ANSI_COLORS_DISABLED') is None:
fmt_str = '\033[%dm%s'
if color is not None:
text = fmt_str % (COLORS[color], text)
if on_color is not None:
text = fmt_str % (HIGHLIGHTS[on_color], text)
if attrs is not None:
for attr in attrs:
text = fmt_str % (ATTRIBUTES[attr], text)
text += RESET
return text
def cprint(text, color=None, on_color=None, attrs=None, **kwargs):
"""Print colorize text.
It accepts arguments of print function.
"""
print((colored(text, color, on_color, attrs)), **kwargs)
if __name__ == '__main__':
print('Current terminal type: %s' % os.getenv('TERM'))
print('Test basic colors:')
cprint('Grey color', 'grey')
cprint('Red color', 'red')
cprint('Green color', 'green')
cprint('Yellow color', 'yellow')
cprint('Blue color', 'blue')
cprint('Magenta color', 'magenta')
cprint('Cyan color', 'cyan')
cprint('White color', 'white')
print(('-' * 78))
print('Test highlights:')
cprint('On grey color', on_color='on_grey')
cprint('On red color', on_color='on_red')
cprint('On green color', on_color='on_green')
cprint('On yellow color', on_color='on_yellow')
cprint('On blue color', on_color='on_blue')
cprint('On magenta color', on_color='on_magenta')
cprint('On cyan color', on_color='on_cyan')
cprint('On white color', color='grey', on_color='on_white')
print('-' * 78)
print('Test attributes:')
cprint('Bold grey color', 'grey', attrs=['bold'])
cprint('Dark red color', 'red', attrs=['dark'])
cprint('Underline green color', 'green', attrs=['underline'])
cprint('Blink yellow color', 'yellow', attrs=['blink'])
cprint('Reversed blue color', 'blue', attrs=['reverse'])
cprint('Concealed Magenta color', 'magenta', attrs=['concealed'])
cprint('Bold underline reverse cyan color', 'cyan',
attrs=['bold', 'underline', 'reverse'])
cprint('Dark blink concealed white color', 'white',
attrs=['dark', 'blink', 'concealed'])
print(('-' * 78))
print('Test mixing:')
cprint('Underline red on grey color', 'red', 'on_grey',
['underline'])
cprint('Reversed green on red color', 'green', 'on_red', ['reverse'])