Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added inquirer directly into Operon until pull request is accepted into
the original project
- Loading branch information
Showing
17 changed files
with
964 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
from __future__ import print_function | ||
|
||
__version__ = '2.2.0' | ||
|
||
try: | ||
from .prompt import prompt | ||
from .questions import Text, Password, Confirm, List, Checkbox, \ | ||
load_from_dict, load_from_json, Path | ||
|
||
__all__ = ['prompt', 'Text', 'Password', 'Confirm', 'List', 'Checkbox', | ||
'load_from_list', 'load_from_dict', 'load_from_json', 'Path'] | ||
except ImportError as e: | ||
print("An error was found, but returning just with the version: %s" % e) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
class InquirerError(Exception): | ||
pass | ||
|
||
|
||
class ValidationError(InquirerError): | ||
def __init__(self, value, *args, **kwargs): | ||
super(ValidationError, self).__init__(*args, **kwargs) | ||
self.value = value | ||
|
||
|
||
class UnknownQuestionTypeError(InquirerError): | ||
pass | ||
|
||
|
||
class Aborted(InquirerError): | ||
pass | ||
|
||
|
||
class EndOfInput(InquirerError): | ||
def __init__(self, selection, *args, **kwargs): | ||
super(EndOfInput, self).__init__(*args, **kwargs) | ||
self.selection = selection | ||
|
||
|
||
class ThemeError(AttributeError): | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import readchar | ||
|
||
|
||
class Event(object): | ||
pass | ||
|
||
|
||
class KeyPressed(Event): | ||
def __init__(self, value): | ||
self.value = value | ||
|
||
|
||
class Repaint(Event): | ||
pass | ||
|
||
|
||
class KeyEventGenerator(object): | ||
def __init__(self, key_generator=None): | ||
self._key_gen = key_generator or readchar.readkey | ||
|
||
def next(self): | ||
return KeyPressed(self._key_gen()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
from .render.console import ConsoleRender | ||
from . import themes | ||
|
||
|
||
def prompt(questions, render=None, answers=None, | ||
theme=themes.Default(), raise_keyboard_interrupt=False): | ||
render = render or ConsoleRender(theme=theme) | ||
answers = answers or {} | ||
|
||
try: | ||
for question in questions: | ||
answers[question.name] = render.render(question, answers) | ||
return answers | ||
except KeyboardInterrupt: | ||
if raise_keyboard_interrupt: | ||
raise | ||
print('') | ||
print('Cancelled by user') | ||
print('') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
# -*- coding: utf-8 -*- | ||
""" | ||
Module that implements the questions types | ||
""" | ||
|
||
import json | ||
|
||
from . import errors | ||
|
||
|
||
def question_factory(kind, *args, **kwargs): | ||
for clazz in (Text, Password, Confirm, List, Checkbox, Path): | ||
if clazz.kind == kind: | ||
return clazz(*args, **kwargs) | ||
raise errors.UnknownQuestionTypeError() | ||
|
||
|
||
def load_from_dict(question_dict): | ||
""" | ||
Load one question from a dict. | ||
It requires the keys 'name' and 'kind'. | ||
:return: The Question object with associated data. | ||
:return type: Question | ||
""" | ||
return question_factory(**question_dict) | ||
|
||
|
||
def load_from_list(question_list): | ||
""" | ||
Load a list of questions from a list of dicts. | ||
It requires the keys 'name' and 'kind' for each dict. | ||
:return: A list of Question objects with associated data. | ||
:return type: List | ||
""" | ||
return [load_from_dict(q) for q in question_list] | ||
|
||
|
||
def load_from_json(question_json): | ||
""" | ||
Load Questions from a JSON string. | ||
:return: A list of Question objects with associated data if the JSON | ||
contains a list or a Question if the JSON contains a dict. | ||
:return type: List or Dict | ||
""" | ||
data = json.loads(question_json) | ||
if isinstance(data, list): | ||
return load_from_list(data) | ||
if isinstance(data, dict): | ||
return load_from_dict(data) | ||
raise TypeError( | ||
'Json contained a %s variable when a dict or list was expected', | ||
type(data)) | ||
|
||
|
||
class TaggedValue(object): | ||
def __init__(self, label, value): | ||
self.label = label | ||
self.value = value | ||
|
||
def __str__(self): | ||
return self.label | ||
|
||
def __repr__(self): | ||
return self.value | ||
|
||
def __eq__(self, other): | ||
if isinstance(other, TaggedValue): | ||
return self.value == other.value | ||
return self.value == other | ||
|
||
def __ne__(self, other): | ||
return not self.__eq__(other) | ||
|
||
|
||
class Question(object): | ||
kind = 'base question' | ||
|
||
def __init__(self, | ||
name, | ||
message='', | ||
choices=None, | ||
default=None, | ||
ignore=False, | ||
validate=True, | ||
show_default=False): | ||
self.name = name | ||
self._message = message | ||
self._choices = choices or [] | ||
self._default = default | ||
self._ignore = ignore | ||
self._validate = validate | ||
self.answers = {} | ||
self.show_default = show_default | ||
|
||
@property | ||
def ignore(self): | ||
return bool(self._solve(self._ignore)) | ||
|
||
@property | ||
def message(self): | ||
return self._solve(self._message) | ||
|
||
@property | ||
def default(self): | ||
return self.answers.get(self.name) or self._solve(self._default) | ||
|
||
@property | ||
def choices_generator(self): | ||
for choice in self._solve(self._choices): | ||
yield ( | ||
TaggedValue(*choice) | ||
if isinstance(choice, tuple) and len(choice) == 2 | ||
else choice | ||
) | ||
|
||
@property | ||
def choices(self): | ||
return list(self.choices_generator) | ||
|
||
def validate(self, current): | ||
try: | ||
if self._solve(self._validate, current): | ||
return | ||
except Exception: | ||
pass | ||
raise errors.ValidationError(current) | ||
|
||
def _solve(self, prop, *args, **kwargs): | ||
if callable(prop): | ||
return prop(self.answers, *args, **kwargs) | ||
if isinstance(prop, str): | ||
return prop.format(**self.answers) | ||
return prop | ||
|
||
|
||
class Text(Question): | ||
kind = 'text' | ||
|
||
|
||
class Password(Question): | ||
kind = 'password' | ||
|
||
|
||
class Confirm(Question): | ||
kind = 'confirm' | ||
|
||
def __init__(self, name, message='', default=False, **kwargs): | ||
super(Confirm, self).__init__(name, message, default=default, **kwargs) | ||
|
||
|
||
class List(Question): | ||
kind = 'list' | ||
|
||
def __init__(self, | ||
name, | ||
message='', | ||
choices=None, | ||
default=None, | ||
ignore=False, | ||
validate=True, | ||
carousel=False): | ||
|
||
super(List, self).__init__( | ||
name, message, choices, | ||
default, ignore, validate | ||
) | ||
self.carousel = carousel | ||
|
||
|
||
class Checkbox(Question): | ||
kind = 'checkbox' | ||
|
||
|
||
class Path(Question): | ||
kind = 'path' | ||
|
||
def __init__(self, | ||
name, | ||
message='', | ||
midtoken_completion=True, | ||
**kwargs): | ||
super(Path, self).__init__(name, message, **kwargs) | ||
self.midtoken_completion = midtoken_completion |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# -*- coding: utf-8 -*- | ||
from .console import ConsoleRender | ||
|
||
|
||
class Render(object): | ||
def __init__(self, impl=ConsoleRender): | ||
self._impl = impl | ||
|
||
def render(self, question, answers): | ||
return self._impl.render(question, answers) |
Oops, something went wrong.