Module jumpscale.sals.chatflows.chatflows
Expand source code
import base64
import sys
import uuid
from importlib import import_module
import inspect
import json
import gevent
import gevent.queue
import html
from jumpscale.loader import j
import stellar_sdk
class Result:
def __init__(self, loader=str):
self._value = None
self._loader = loader
@property
def value(self):
return self._value
@value.setter
def value(self, value):
self._value = self._loader(value)
class Form:
def __init__(self, session):
self._session = session
self.fields = []
self.results = []
def ask(self, msg=None, **kwargs):
self._session.send_data(
{"category": "form", "msg": msg, "fields": self.fields, "kwargs": kwargs}, is_slide=True
)
results = j.data.serializers.json.loads(self._session._queue_in.get())
for result, resobject in zip(results, self.results):
resobject.value = result
def _append(self, msg, loader=str):
self.fields.append(msg)
result = Result(loader)
self.results.append(result)
return result
def string_ask(self, msg, **kwargs):
return self._append(self._session.string_msg(msg, **kwargs))
def int_ask(self, msg, **kwargs):
return self._append(self._session.int_msg(msg, **kwargs), int)
def secret_ask(self, msg, **kwargs):
return self._append(self._session.secret_msg(msg, **kwargs))
def datetime_picker(self, msg, **kwargs):
return self._append(self._session.datetime_picker_msg(msg, **kwargs))
def multi_list_choice(self, msg, options, **kwargs):
return self._append(self._session.multi_list_choice_msg(msg, options, **kwargs))
def upload_file(self, msg, **kwargs):
return self._append(self._session.upload_file_msg(msg, **kwargs))
def multi_choice(self, msg, options, **kwargs):
return self._append(self._session.multi_choice_msg(msg, options, **kwargs), j.data.serializers.json.loads)
def single_choice(self, msg, options, **kwargs):
return self._append(self._session.single_choice_msg(msg, options, **kwargs))
def drop_down_choice(self, msg, options, **kwargs):
return self._append(self._session.drop_down_choice_msg(msg, options, **kwargs))
class GedisChatBot:
"""
Contains the basic helper methods for asking questions
It also have the main queues q_in, q_out that are used to pass questions and answers between browser and server
"""
steps = []
title = "Zero Chat Bot"
alert_view_url = None
def __init__(self, **kwargs):
"""
Keyword Args
any extra kwargs that is passed while creating the session
(i.e. can be used for passing any query parameters)
"""
self.session_id = str(uuid.uuid4())
self.kwargs = kwargs
self.spawn = kwargs.get("spawn", True)
self._state = {}
self._current_step = 0
self._steps_info = {}
self._last_output = None
self._fetch_greenlet = None
self._greenlet = None
self._queue_out = gevent.queue.Queue()
self._queue_in = gevent.queue.Queue()
self._start()
@property
def step_info(self):
return self._steps_info.setdefault(self._current_step, {"slide": 0})
@property
def is_first_slide(self):
return self.step_info.get("slide", 1) == 1
@property
def is_first_step(self):
return self._current_step == 0
@property
def is_last_step(self):
return self._current_step >= len(self.steps) - 1
@property
def info(self):
previous = True
if self.is_first_slide:
if self.is_first_step or not self.step_info.get("previous"):
previous = False
return {
"step": self._current_step + 1,
"steps": len(self.steps),
"title": self.step_info.get("title"),
"previous": previous,
"last_step": self.is_last_step,
"first_step": self.is_first_step,
"first_slide": self.is_first_slide,
"slide": self.step_info.get("slide", 1),
"final_step": self.step_info.get("final_step"),
}
def _execute_current_step(self, spawn=None):
if spawn is None:
spawn = self.spawn
def wrapper(step_name):
internal_error = False
try:
getattr(self, step_name)()
except StopChatFlow as e:
internal_error = True
j.logger.exception(f"chatflow stopped in step {step_name}. exception: {str(e)}", exception=e)
traceback_info = j.tools.errorhandler.get_traceback()
j.tools.alerthandler.alert_raise(
app_name="chatflows",
category="internal_errors",
message=str(e),
alert_type="exception",
traceback=traceback_info,
)
if e.msg:
self.send_error(
e.msg + f". Use the refresh button on the upper right to restart {self.title} creation",
**e.kwargs,
)
self.send_data({"category": "end"})
except Exception as e:
message = "Something wrong happened"
if isinstance(e, stellar_sdk.exceptions.BadRequestError) and "op_underfunded" in e.extras.get(
"result_codes", {}
).get("operations", []):
message = "Not enough funds"
internal_error = True
j.logger.exception(f"error when executing step {step_name}. exception: {str(e)}", exception=e)
traceback_info = j.tools.errorhandler.get_traceback()
alert = j.tools.alerthandler.alert_raise(
app_name="chatflows",
category="internal_errors",
message=str(e),
alert_type="exception",
traceback=traceback_info,
)
username = self.user_info()["username"]
if self.alert_view_url:
self.send_error(
f"""{message}, please check alert: <a href="{self.alert_view_url}/{alert.id}" target="_parent">{alert.id} </a>. This could occur if Stellar service was down."""
f"Use the refresh button on the upper right to restart {self.title} creation",
md=True,
html=True,
)
elif username in j.core.identity.me.admins:
self.send_error(
f"""{message}, please check alert: <a href="/admin/#/alerts/{alert.id}" target="_parent">{alert.id} </a>. This could occur if Stellar service was down."""
f"Use the refresh button on the upper right to restart {self.title} creation",
md=True,
html=True,
)
else:
self.send_error(
f"Something wrong happened, please contact support with alert ID: {alert.id}\n"
f"Use the refresh button on the upper right to restart {self.title} creation"
)
self.send_data({"category": "end"})
if not internal_error:
if self.is_last_step:
self.send_data({"category": "end"})
else:
self._current_step += 1
self._execute_current_step(spawn=False)
step_name = self.steps[self._current_step]
self.step_info["slide"] = 0
if spawn:
self._greenlet = gevent.spawn(wrapper, step_name)
else:
wrapper(step_name)
def _start(self):
self._execute_current_step()
def go_next(self):
self._current_step += 1
self._execute_current_step()
def go_back(self):
if self.is_first_slide:
if self.is_first_step:
return
else:
self._current_step -= 1
self._greenlet.kill()
return self._execute_current_step()
def get_work(self, restore=False):
if self._fetch_greenlet:
if not self._fetch_greenlet.ready():
self._fetch_greenlet.kill()
if restore and self._last_output:
return self._last_output
self._fetch_greenlet = gevent.spawn(self._queue_out.get)
result = self._fetch_greenlet.get()
if not isinstance(result, gevent.GreenletExit):
return result
def set_work(self, data):
return self._queue_in.put(data)
def send_data(self, data, is_slide=False):
data.setdefault("kwargs", {})
retry = data["kwargs"].pop("retry", False)
if is_slide and not retry:
self.step_info["slide"] += 1
output = {"info": self.info, "payload": data}
self._last_output = output
self._queue_out.put(output)
def send_error(self, message, **kwargs):
self.send_data({"category": "error", "msg": message, "kwargs": kwargs})
self._queue_in.get()
def ask(self, data):
self.send_data(data, is_slide=True)
return self._queue_in.get()
def user_info(self, **kwargs):
self.send_data({"category": "user_info", "kwargs": kwargs})
result = j.data.serializers.json.loads(self._queue_in.get())
return result
def string_msg(self, msg, **kwargs):
return {"category": "string_ask", "msg": msg, "kwargs": kwargs}
def string_ask(self, msg, **kwargs):
"""Ask for a string value
Args:
msg (str): message text
Keyword Arguments:
required (bool): flag to make this field required
md (bool): render message as markdown
html (bool): render message as html
min_length (int): min length
max_length (int): max length
Returns:
str: user input
"""
return self.ask(self.string_msg(msg, **kwargs))
def secret_msg(self, msg, **kwargs):
return {"category": "secret_ask", "msg": msg, "kwargs": kwargs}
def secret_ask(self, msg, **kwargs):
"""Ask for a secret value
Args:
msg (str): message text
Keyword Arguments:
required (bool): flag to make this field required
md (bool): render message as markdown
html (bool): render message as html
min_length (int): min length
max_length (int): max length
Returns:
str: user input
"""
return self.ask(self.secret_msg(msg, **kwargs))
def int_msg(self, msg, **kwargs):
return {"category": "int_ask", "msg": msg, "kwargs": kwargs}
def int_ask(self, msg, **kwargs):
"""Ask for a inegert value
Args:
msg (str): message text
Keyword Arguments:
required (bool): flag to make this field required
md (bool): render message as markdown
html (bool): render message as html
min (int): min value
max (int): max value
Returns:
str: user input
"""
result = self.ask(self.int_msg(msg, **kwargs))
if result:
return int(result)
def text_msg(self, msg, **kwargs):
return {"category": "text_ask", "msg": msg, "kwargs": kwargs}
def text_ask(self, msg, **kwargs):
"""Ask for a multi line string value
Args:
msg (str): message text
Keyword Arguments:
required (bool): flag to make this field required
md (bool): render message as markdown
html (bool): render message as html
Returns:
str: user input
"""
return self.ask(self.text_msg(msg, **kwargs))
def single_choice_msg(self, msg, options, **kwargs):
return {"category": "single_choice", "msg": msg, "options": options, "kwargs": kwargs}
def single_choice(self, msg, options, **kwargs):
"""Ask for a single option
Args:
msg (str): message text
Keyword Arguments:
required (bool): flag to make this field required
md (bool): render message as markdown
html (bool): render message as html
Returns:
str: user input
"""
return self.ask(self.single_choice_msg(msg, options, **kwargs))
def multi_choice_msg(self, msg, options, **kwargs):
return {"category": "multi_choice", "msg": msg, "options": options, "kwargs": kwargs}
def multi_choice(self, msg, options, **kwargs):
"""Ask for a multiple options
Args:
msg (str): message text
Keyword Arguments:
required (bool): flag to make this field required
md (bool): render message as markdown
html (bool): render message as html
min_options (int): min number of selected options
max_options (int): max number selected options
Returns:
str: user input
"""
result = self.ask(self.multi_choice_msg(msg, options, **kwargs))
return j.data.serializers.json.loads(result)
def multi_list_choice_msg(self, msg, options, **kwargs):
return {"category": "multi_list_choice", "msg": msg, "options": options, "kwargs": kwargs}
def multi_list_choice(self, msg, options, **kwargs):
"""Ask for a multiple options
Args:
msg (str): message text
Keyword Arguments:
required (bool): flag to make this field required
md (bool): render message as markdown
html (bool): render message as html
min_options (int): min number of selected options
max_options (int): max number selected options
Returns:
str: user input
"""
result = self.ask(self.multi_list_choice_msg(msg, options, **kwargs))
return j.data.serializers.json.loads(result)
def drop_down_choice_msg(self, msg, options, **kwargs):
return {"category": "drop_down_choice", "msg": msg, "options": options, "kwargs": kwargs}
def drop_down_choice(self, msg, options, **kwargs):
"""Ask for a single options using dropdown
Args:
msg (str): message text
Keyword Arguments:
required (bool): flag to make this field required
md (bool): render message as markdown
html (bool): render message as html
Returns:
str: user input
"""
return self.ask(self.drop_down_choice_msg(msg, options, **kwargs))
def autocomplete_drop_down(self, msg, options, **kwargs):
"""Ask for a single options using dropdown with auto completion
Args:
msg (str): message text
Keyword Arguments:
required (bool): flag to make this field required
md (bool): render message as markdown
html (bool): render message as html
Returns:
str: user input
"""
return self.drop_down_choice(msg, options, auto_complete=True, **kwargs)
def datetime_picker_msg(self, msg, **kwargs):
return {"category": "datetime_picker", "msg": msg, "kwargs": kwargs}
def datetime_picker(self, msg, **kwargs):
"""Ask for a datetime
Args:
msg (str): message text
Keyword Arguments:
required (bool): flag to make this field required
md (bool): render message as markdown
html (bool): render message as html
Returns:
int: timestamp
"""
result = self.ask(self.datetime_picker_msg(msg, **kwargs))
if result:
return int(result)
def time_delta_msg(self, msg, **kwargs):
return {"category": "time_delta", "msg": msg, "kwargs": kwargs}
def time_delta_ask(self, msg, **kwargs):
"""Ask for a time delta example: 1Y 1M 1w 2d 1h
Args:
msg (str): message text
Keyword Arguments:
required (bool): flag to make this field required
md (bool): render message as markdown
html (bool): render message as html
Returns:
datetime.datetime: user input
"""
result = self.ask(self.time_delta_msg(msg, timedelta=True, **kwargs))
return j.data.time.get(result).humanize()
def location_msg(self, msg, **kwargs):
return {"category": "location_ask", "msg": msg, "kwargs": kwargs}
def location_ask(self, msg, **kwargs):
"""Ask for a location [lng, lat]
Args:
msg (str): message text
Keyword Arguments:
required (bool): flag to make this field required
md (bool): render message as markdown
html (bool): render message as html
Returns:
list: list([lat, lng])
"""
result = self.ask(self.location_msg(msg, **kwargs))
return j.data.serializers.json.loads(result)
def download_file(self, msg, data, filename, **kwargs):
"""Add a download button to download data as a file
Args:
msg (str): message text
data (str): the data to be in the file
filename (str): file name
Keyword Arguments:
md (bool): render message as markdown
html (bool): render message as html
"""
self.ask({"category": "download_file", "msg": msg, "data": data, "filename": filename, "kwargs": kwargs})
def upload_file_msg(self, msg, **kwargs):
return {"category": "upload_file", "msg": msg, "kwargs": kwargs}
def upload_file(self, msg, **kwargs):
"""Ask for a file to be uploaded
Args:
msg (str): message text
Keyword Arguments:
required (bool): flag to make this field required
md (bool): render message as markdown
html (bool): render message as html
max_size (int): file max size
allowed_types: list of allowed types example : ['text/plain']
Returns:
str: file content
"""
return self.ask(self.upload_file_msg(msg, **kwargs))
def qrcode_show(self, msg, data, scale=10, **kwargs):
"""Show QR code as an image
Args:
msg (str): message
data (str): data to be encoded
scale (int, optional): qrcode scale. Defaults to 10.
Keyword Arguments:
md (bool): render message as markdown
html (bool): render message as html
"""
qrcode = j.tools.qrcode.base64_get(data, scale=scale)
self.send_data({"category": "qrcode_show", "msg": msg, "qrcode": qrcode, "kwargs": kwargs}, is_slide=True)
self._queue_in.get()
def md_msg(self, msg, **kwargs):
return {"category": "md_show", "msg": msg, "kwargs": kwargs}
def md_show(self, msg, **kwargs):
"""Show markdown
Args:
msg (str): markdown string
"""
self.send_data(self.md_msg(msg, **kwargs), is_slide=True)
self._queue_in.get()
def md_show_confirm(self, data, **kwargs):
"""Show a table contains the keys and values of the data dict
Args:
data (dict): the data to be shown in the table
"""
if "msg" in kwargs:
msg = kwargs["msg"]
else:
msg = "Please make sure of the entered values before starting deployment"
self.send_data({"category": "confirm", "data": data, "kwargs": kwargs, "msg": msg}, is_slide=True)
self._queue_in.get()
def loading_show(self, msg, wait, **kwargs):
"""Show a progress bar
Args:
msg (str): message
wait (int): the duration (in seconds) of the progress bar
Keyword Arguments:
md (bool): render message as markdown
html (bool): render message as html
"""
data = {"category": "loading", "msg": msg, "kwargs": kwargs}
for i in range(wait):
data["value"] = (i / wait) * 100
self.send_data(data)
gevent.sleep(1)
def md_show_update(self, msg, **kwargs):
self.send_data({"category": "infinite_loading", "msg": msg, "kwargs": kwargs}, is_slide=False)
def multi_values_ask(self, msg, **kwargs):
"""Ask for multiple values
Args:
msg (str): message text
Keyword Arguments:
required (bool): flag to make this field required
md (bool): render message as markdown
html (bool): render message as html
Returns:
dict: the result as a dict
"""
result = self.ask({"category": "ask_multi_values", "msg": msg, "kwargs": kwargs})
return j.data.serializers.json.loads(result)
def new_form(self):
"""Create a new form
Returns:
Form: form object
"""
return Form(self)
def stop(self, msg=None, **kwargs):
raise StopChatFlow(msg=msg, **kwargs)
def end(self):
self.send_data({"category": "end"})
def chatflow_step(title=None, final_step=False, disable_previous=False):
def decorator(func):
def wrapper(*args, **kwargs):
self_ = args[0]
self_.step_info.update(title=title, slide=0, previous=(not disable_previous), final_step=final_step)
return func(*args, **kwargs)
return wrapper
return decorator
class StopChatFlow(Exception):
def __init__(self, msg=None, **kwargs):
super().__init__(self, msg)
self.msg = msg
self.kwargs = kwargs
Functions
def chatflow_step(title=None, final_step=False, disable_previous=False)
-
Expand source code
def chatflow_step(title=None, final_step=False, disable_previous=False): def decorator(func): def wrapper(*args, **kwargs): self_ = args[0] self_.step_info.update(title=title, slide=0, previous=(not disable_previous), final_step=final_step) return func(*args, **kwargs) return wrapper return decorator
Classes
class Form (session)
-
Expand source code
class Form: def __init__(self, session): self._session = session self.fields = [] self.results = [] def ask(self, msg=None, **kwargs): self._session.send_data( {"category": "form", "msg": msg, "fields": self.fields, "kwargs": kwargs}, is_slide=True ) results = j.data.serializers.json.loads(self._session._queue_in.get()) for result, resobject in zip(results, self.results): resobject.value = result def _append(self, msg, loader=str): self.fields.append(msg) result = Result(loader) self.results.append(result) return result def string_ask(self, msg, **kwargs): return self._append(self._session.string_msg(msg, **kwargs)) def int_ask(self, msg, **kwargs): return self._append(self._session.int_msg(msg, **kwargs), int) def secret_ask(self, msg, **kwargs): return self._append(self._session.secret_msg(msg, **kwargs)) def datetime_picker(self, msg, **kwargs): return self._append(self._session.datetime_picker_msg(msg, **kwargs)) def multi_list_choice(self, msg, options, **kwargs): return self._append(self._session.multi_list_choice_msg(msg, options, **kwargs)) def upload_file(self, msg, **kwargs): return self._append(self._session.upload_file_msg(msg, **kwargs)) def multi_choice(self, msg, options, **kwargs): return self._append(self._session.multi_choice_msg(msg, options, **kwargs), j.data.serializers.json.loads) def single_choice(self, msg, options, **kwargs): return self._append(self._session.single_choice_msg(msg, options, **kwargs)) def drop_down_choice(self, msg, options, **kwargs): return self._append(self._session.drop_down_choice_msg(msg, options, **kwargs))
Methods
def ask(self, msg=None, **kwargs)
-
Expand source code
def ask(self, msg=None, **kwargs): self._session.send_data( {"category": "form", "msg": msg, "fields": self.fields, "kwargs": kwargs}, is_slide=True ) results = j.data.serializers.json.loads(self._session._queue_in.get()) for result, resobject in zip(results, self.results): resobject.value = result
def datetime_picker(self, msg, **kwargs)
-
Expand source code
def datetime_picker(self, msg, **kwargs): return self._append(self._session.datetime_picker_msg(msg, **kwargs))
def drop_down_choice(self, msg, options, **kwargs)
-
Expand source code
def drop_down_choice(self, msg, options, **kwargs): return self._append(self._session.drop_down_choice_msg(msg, options, **kwargs))
def int_ask(self, msg, **kwargs)
-
Expand source code
def int_ask(self, msg, **kwargs): return self._append(self._session.int_msg(msg, **kwargs), int)
def multi_choice(self, msg, options, **kwargs)
-
Expand source code
def multi_choice(self, msg, options, **kwargs): return self._append(self._session.multi_choice_msg(msg, options, **kwargs), j.data.serializers.json.loads)
def multi_list_choice(self, msg, options, **kwargs)
-
Expand source code
def multi_list_choice(self, msg, options, **kwargs): return self._append(self._session.multi_list_choice_msg(msg, options, **kwargs))
def secret_ask(self, msg, **kwargs)
-
Expand source code
def secret_ask(self, msg, **kwargs): return self._append(self._session.secret_msg(msg, **kwargs))
def single_choice(self, msg, options, **kwargs)
-
Expand source code
def single_choice(self, msg, options, **kwargs): return self._append(self._session.single_choice_msg(msg, options, **kwargs))
def string_ask(self, msg, **kwargs)
-
Expand source code
def string_ask(self, msg, **kwargs): return self._append(self._session.string_msg(msg, **kwargs))
def upload_file(self, msg, **kwargs)
-
Expand source code
def upload_file(self, msg, **kwargs): return self._append(self._session.upload_file_msg(msg, **kwargs))
class GedisChatBot (**kwargs)
-
Contains the basic helper methods for asking questions It also have the main queues q_in, q_out that are used to pass questions and answers between browser and server
Keyword Args any extra kwargs that is passed while creating the session (i.e. can be used for passing any query parameters)
Expand source code
class GedisChatBot: """ Contains the basic helper methods for asking questions It also have the main queues q_in, q_out that are used to pass questions and answers between browser and server """ steps = [] title = "Zero Chat Bot" alert_view_url = None def __init__(self, **kwargs): """ Keyword Args any extra kwargs that is passed while creating the session (i.e. can be used for passing any query parameters) """ self.session_id = str(uuid.uuid4()) self.kwargs = kwargs self.spawn = kwargs.get("spawn", True) self._state = {} self._current_step = 0 self._steps_info = {} self._last_output = None self._fetch_greenlet = None self._greenlet = None self._queue_out = gevent.queue.Queue() self._queue_in = gevent.queue.Queue() self._start() @property def step_info(self): return self._steps_info.setdefault(self._current_step, {"slide": 0}) @property def is_first_slide(self): return self.step_info.get("slide", 1) == 1 @property def is_first_step(self): return self._current_step == 0 @property def is_last_step(self): return self._current_step >= len(self.steps) - 1 @property def info(self): previous = True if self.is_first_slide: if self.is_first_step or not self.step_info.get("previous"): previous = False return { "step": self._current_step + 1, "steps": len(self.steps), "title": self.step_info.get("title"), "previous": previous, "last_step": self.is_last_step, "first_step": self.is_first_step, "first_slide": self.is_first_slide, "slide": self.step_info.get("slide", 1), "final_step": self.step_info.get("final_step"), } def _execute_current_step(self, spawn=None): if spawn is None: spawn = self.spawn def wrapper(step_name): internal_error = False try: getattr(self, step_name)() except StopChatFlow as e: internal_error = True j.logger.exception(f"chatflow stopped in step {step_name}. exception: {str(e)}", exception=e) traceback_info = j.tools.errorhandler.get_traceback() j.tools.alerthandler.alert_raise( app_name="chatflows", category="internal_errors", message=str(e), alert_type="exception", traceback=traceback_info, ) if e.msg: self.send_error( e.msg + f". Use the refresh button on the upper right to restart {self.title} creation", **e.kwargs, ) self.send_data({"category": "end"}) except Exception as e: message = "Something wrong happened" if isinstance(e, stellar_sdk.exceptions.BadRequestError) and "op_underfunded" in e.extras.get( "result_codes", {} ).get("operations", []): message = "Not enough funds" internal_error = True j.logger.exception(f"error when executing step {step_name}. exception: {str(e)}", exception=e) traceback_info = j.tools.errorhandler.get_traceback() alert = j.tools.alerthandler.alert_raise( app_name="chatflows", category="internal_errors", message=str(e), alert_type="exception", traceback=traceback_info, ) username = self.user_info()["username"] if self.alert_view_url: self.send_error( f"""{message}, please check alert: <a href="{self.alert_view_url}/{alert.id}" target="_parent">{alert.id} </a>. This could occur if Stellar service was down.""" f"Use the refresh button on the upper right to restart {self.title} creation", md=True, html=True, ) elif username in j.core.identity.me.admins: self.send_error( f"""{message}, please check alert: <a href="/admin/#/alerts/{alert.id}" target="_parent">{alert.id} </a>. This could occur if Stellar service was down.""" f"Use the refresh button on the upper right to restart {self.title} creation", md=True, html=True, ) else: self.send_error( f"Something wrong happened, please contact support with alert ID: {alert.id}\n" f"Use the refresh button on the upper right to restart {self.title} creation" ) self.send_data({"category": "end"}) if not internal_error: if self.is_last_step: self.send_data({"category": "end"}) else: self._current_step += 1 self._execute_current_step(spawn=False) step_name = self.steps[self._current_step] self.step_info["slide"] = 0 if spawn: self._greenlet = gevent.spawn(wrapper, step_name) else: wrapper(step_name) def _start(self): self._execute_current_step() def go_next(self): self._current_step += 1 self._execute_current_step() def go_back(self): if self.is_first_slide: if self.is_first_step: return else: self._current_step -= 1 self._greenlet.kill() return self._execute_current_step() def get_work(self, restore=False): if self._fetch_greenlet: if not self._fetch_greenlet.ready(): self._fetch_greenlet.kill() if restore and self._last_output: return self._last_output self._fetch_greenlet = gevent.spawn(self._queue_out.get) result = self._fetch_greenlet.get() if not isinstance(result, gevent.GreenletExit): return result def set_work(self, data): return self._queue_in.put(data) def send_data(self, data, is_slide=False): data.setdefault("kwargs", {}) retry = data["kwargs"].pop("retry", False) if is_slide and not retry: self.step_info["slide"] += 1 output = {"info": self.info, "payload": data} self._last_output = output self._queue_out.put(output) def send_error(self, message, **kwargs): self.send_data({"category": "error", "msg": message, "kwargs": kwargs}) self._queue_in.get() def ask(self, data): self.send_data(data, is_slide=True) return self._queue_in.get() def user_info(self, **kwargs): self.send_data({"category": "user_info", "kwargs": kwargs}) result = j.data.serializers.json.loads(self._queue_in.get()) return result def string_msg(self, msg, **kwargs): return {"category": "string_ask", "msg": msg, "kwargs": kwargs} def string_ask(self, msg, **kwargs): """Ask for a string value Args: msg (str): message text Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html min_length (int): min length max_length (int): max length Returns: str: user input """ return self.ask(self.string_msg(msg, **kwargs)) def secret_msg(self, msg, **kwargs): return {"category": "secret_ask", "msg": msg, "kwargs": kwargs} def secret_ask(self, msg, **kwargs): """Ask for a secret value Args: msg (str): message text Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html min_length (int): min length max_length (int): max length Returns: str: user input """ return self.ask(self.secret_msg(msg, **kwargs)) def int_msg(self, msg, **kwargs): return {"category": "int_ask", "msg": msg, "kwargs": kwargs} def int_ask(self, msg, **kwargs): """Ask for a inegert value Args: msg (str): message text Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html min (int): min value max (int): max value Returns: str: user input """ result = self.ask(self.int_msg(msg, **kwargs)) if result: return int(result) def text_msg(self, msg, **kwargs): return {"category": "text_ask", "msg": msg, "kwargs": kwargs} def text_ask(self, msg, **kwargs): """Ask for a multi line string value Args: msg (str): message text Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html Returns: str: user input """ return self.ask(self.text_msg(msg, **kwargs)) def single_choice_msg(self, msg, options, **kwargs): return {"category": "single_choice", "msg": msg, "options": options, "kwargs": kwargs} def single_choice(self, msg, options, **kwargs): """Ask for a single option Args: msg (str): message text Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html Returns: str: user input """ return self.ask(self.single_choice_msg(msg, options, **kwargs)) def multi_choice_msg(self, msg, options, **kwargs): return {"category": "multi_choice", "msg": msg, "options": options, "kwargs": kwargs} def multi_choice(self, msg, options, **kwargs): """Ask for a multiple options Args: msg (str): message text Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html min_options (int): min number of selected options max_options (int): max number selected options Returns: str: user input """ result = self.ask(self.multi_choice_msg(msg, options, **kwargs)) return j.data.serializers.json.loads(result) def multi_list_choice_msg(self, msg, options, **kwargs): return {"category": "multi_list_choice", "msg": msg, "options": options, "kwargs": kwargs} def multi_list_choice(self, msg, options, **kwargs): """Ask for a multiple options Args: msg (str): message text Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html min_options (int): min number of selected options max_options (int): max number selected options Returns: str: user input """ result = self.ask(self.multi_list_choice_msg(msg, options, **kwargs)) return j.data.serializers.json.loads(result) def drop_down_choice_msg(self, msg, options, **kwargs): return {"category": "drop_down_choice", "msg": msg, "options": options, "kwargs": kwargs} def drop_down_choice(self, msg, options, **kwargs): """Ask for a single options using dropdown Args: msg (str): message text Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html Returns: str: user input """ return self.ask(self.drop_down_choice_msg(msg, options, **kwargs)) def autocomplete_drop_down(self, msg, options, **kwargs): """Ask for a single options using dropdown with auto completion Args: msg (str): message text Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html Returns: str: user input """ return self.drop_down_choice(msg, options, auto_complete=True, **kwargs) def datetime_picker_msg(self, msg, **kwargs): return {"category": "datetime_picker", "msg": msg, "kwargs": kwargs} def datetime_picker(self, msg, **kwargs): """Ask for a datetime Args: msg (str): message text Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html Returns: int: timestamp """ result = self.ask(self.datetime_picker_msg(msg, **kwargs)) if result: return int(result) def time_delta_msg(self, msg, **kwargs): return {"category": "time_delta", "msg": msg, "kwargs": kwargs} def time_delta_ask(self, msg, **kwargs): """Ask for a time delta example: 1Y 1M 1w 2d 1h Args: msg (str): message text Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html Returns: datetime.datetime: user input """ result = self.ask(self.time_delta_msg(msg, timedelta=True, **kwargs)) return j.data.time.get(result).humanize() def location_msg(self, msg, **kwargs): return {"category": "location_ask", "msg": msg, "kwargs": kwargs} def location_ask(self, msg, **kwargs): """Ask for a location [lng, lat] Args: msg (str): message text Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html Returns: list: list([lat, lng]) """ result = self.ask(self.location_msg(msg, **kwargs)) return j.data.serializers.json.loads(result) def download_file(self, msg, data, filename, **kwargs): """Add a download button to download data as a file Args: msg (str): message text data (str): the data to be in the file filename (str): file name Keyword Arguments: md (bool): render message as markdown html (bool): render message as html """ self.ask({"category": "download_file", "msg": msg, "data": data, "filename": filename, "kwargs": kwargs}) def upload_file_msg(self, msg, **kwargs): return {"category": "upload_file", "msg": msg, "kwargs": kwargs} def upload_file(self, msg, **kwargs): """Ask for a file to be uploaded Args: msg (str): message text Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html max_size (int): file max size allowed_types: list of allowed types example : ['text/plain'] Returns: str: file content """ return self.ask(self.upload_file_msg(msg, **kwargs)) def qrcode_show(self, msg, data, scale=10, **kwargs): """Show QR code as an image Args: msg (str): message data (str): data to be encoded scale (int, optional): qrcode scale. Defaults to 10. Keyword Arguments: md (bool): render message as markdown html (bool): render message as html """ qrcode = j.tools.qrcode.base64_get(data, scale=scale) self.send_data({"category": "qrcode_show", "msg": msg, "qrcode": qrcode, "kwargs": kwargs}, is_slide=True) self._queue_in.get() def md_msg(self, msg, **kwargs): return {"category": "md_show", "msg": msg, "kwargs": kwargs} def md_show(self, msg, **kwargs): """Show markdown Args: msg (str): markdown string """ self.send_data(self.md_msg(msg, **kwargs), is_slide=True) self._queue_in.get() def md_show_confirm(self, data, **kwargs): """Show a table contains the keys and values of the data dict Args: data (dict): the data to be shown in the table """ if "msg" in kwargs: msg = kwargs["msg"] else: msg = "Please make sure of the entered values before starting deployment" self.send_data({"category": "confirm", "data": data, "kwargs": kwargs, "msg": msg}, is_slide=True) self._queue_in.get() def loading_show(self, msg, wait, **kwargs): """Show a progress bar Args: msg (str): message wait (int): the duration (in seconds) of the progress bar Keyword Arguments: md (bool): render message as markdown html (bool): render message as html """ data = {"category": "loading", "msg": msg, "kwargs": kwargs} for i in range(wait): data["value"] = (i / wait) * 100 self.send_data(data) gevent.sleep(1) def md_show_update(self, msg, **kwargs): self.send_data({"category": "infinite_loading", "msg": msg, "kwargs": kwargs}, is_slide=False) def multi_values_ask(self, msg, **kwargs): """Ask for multiple values Args: msg (str): message text Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html Returns: dict: the result as a dict """ result = self.ask({"category": "ask_multi_values", "msg": msg, "kwargs": kwargs}) return j.data.serializers.json.loads(result) def new_form(self): """Create a new form Returns: Form: form object """ return Form(self) def stop(self, msg=None, **kwargs): raise StopChatFlow(msg=msg, **kwargs) def end(self): self.send_data({"category": "end"})
Subclasses
Class variables
var alert_view_url
var steps
var title
Instance variables
var info
-
Expand source code
@property def info(self): previous = True if self.is_first_slide: if self.is_first_step or not self.step_info.get("previous"): previous = False return { "step": self._current_step + 1, "steps": len(self.steps), "title": self.step_info.get("title"), "previous": previous, "last_step": self.is_last_step, "first_step": self.is_first_step, "first_slide": self.is_first_slide, "slide": self.step_info.get("slide", 1), "final_step": self.step_info.get("final_step"), }
var is_first_slide
-
Expand source code
@property def is_first_slide(self): return self.step_info.get("slide", 1) == 1
var is_first_step
-
Expand source code
@property def is_first_step(self): return self._current_step == 0
var is_last_step
-
Expand source code
@property def is_last_step(self): return self._current_step >= len(self.steps) - 1
var step_info
-
Expand source code
@property def step_info(self): return self._steps_info.setdefault(self._current_step, {"slide": 0})
Methods
def ask(self, data)
-
Expand source code
def ask(self, data): self.send_data(data, is_slide=True) return self._queue_in.get()
def autocomplete_drop_down(self, msg, options, **kwargs)
-
Ask for a single options using dropdown with auto completion
Args
msg
:str
- message text
Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html
Returns
str
- user input
Expand source code
def autocomplete_drop_down(self, msg, options, **kwargs): """Ask for a single options using dropdown with auto completion Args: msg (str): message text Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html Returns: str: user input """ return self.drop_down_choice(msg, options, auto_complete=True, **kwargs)
def datetime_picker(self, msg, **kwargs)
-
Ask for a datetime
Args
msg
:str
- message text
Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html
Returns
int
- timestamp
Expand source code
def datetime_picker(self, msg, **kwargs): """Ask for a datetime Args: msg (str): message text Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html Returns: int: timestamp """ result = self.ask(self.datetime_picker_msg(msg, **kwargs)) if result: return int(result)
def datetime_picker_msg(self, msg, **kwargs)
-
Expand source code
def datetime_picker_msg(self, msg, **kwargs): return {"category": "datetime_picker", "msg": msg, "kwargs": kwargs}
def download_file(self, msg, data, filename, **kwargs)
-
Add a download button to download data as a file
Args
msg
:str
- message text
data
:str
- the data to be in the file
filename
:str
- file name
Keyword Arguments: md (bool): render message as markdown html (bool): render message as html
Expand source code
def download_file(self, msg, data, filename, **kwargs): """Add a download button to download data as a file Args: msg (str): message text data (str): the data to be in the file filename (str): file name Keyword Arguments: md (bool): render message as markdown html (bool): render message as html """ self.ask({"category": "download_file", "msg": msg, "data": data, "filename": filename, "kwargs": kwargs})
def drop_down_choice(self, msg, options, **kwargs)
-
Ask for a single options using dropdown
Args
msg
:str
- message text
Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html
Returns
str
- user input
Expand source code
def drop_down_choice(self, msg, options, **kwargs): """Ask for a single options using dropdown Args: msg (str): message text Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html Returns: str: user input """ return self.ask(self.drop_down_choice_msg(msg, options, **kwargs))
def drop_down_choice_msg(self, msg, options, **kwargs)
-
Expand source code
def drop_down_choice_msg(self, msg, options, **kwargs): return {"category": "drop_down_choice", "msg": msg, "options": options, "kwargs": kwargs}
def end(self)
-
Expand source code
def end(self): self.send_data({"category": "end"})
def get_work(self, restore=False)
-
Expand source code
def get_work(self, restore=False): if self._fetch_greenlet: if not self._fetch_greenlet.ready(): self._fetch_greenlet.kill() if restore and self._last_output: return self._last_output self._fetch_greenlet = gevent.spawn(self._queue_out.get) result = self._fetch_greenlet.get() if not isinstance(result, gevent.GreenletExit): return result
def go_back(self)
-
Expand source code
def go_back(self): if self.is_first_slide: if self.is_first_step: return else: self._current_step -= 1 self._greenlet.kill() return self._execute_current_step()
def go_next(self)
-
Expand source code
def go_next(self): self._current_step += 1 self._execute_current_step()
def int_ask(self, msg, **kwargs)
-
Ask for a inegert value
Args
msg
:str
- message text
Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html min (int): min value max (int): max value
Returns
str
- user input
Expand source code
def int_ask(self, msg, **kwargs): """Ask for a inegert value Args: msg (str): message text Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html min (int): min value max (int): max value Returns: str: user input """ result = self.ask(self.int_msg(msg, **kwargs)) if result: return int(result)
def int_msg(self, msg, **kwargs)
-
Expand source code
def int_msg(self, msg, **kwargs): return {"category": "int_ask", "msg": msg, "kwargs": kwargs}
def loading_show(self, msg, wait, **kwargs)
-
Show a progress bar
Args
msg
:str
- message
wait
:int
- the duration (in seconds) of the progress bar
Keyword Arguments: md (bool): render message as markdown html (bool): render message as html
Expand source code
def loading_show(self, msg, wait, **kwargs): """Show a progress bar Args: msg (str): message wait (int): the duration (in seconds) of the progress bar Keyword Arguments: md (bool): render message as markdown html (bool): render message as html """ data = {"category": "loading", "msg": msg, "kwargs": kwargs} for i in range(wait): data["value"] = (i / wait) * 100 self.send_data(data) gevent.sleep(1)
def location_ask(self, msg, **kwargs)
-
Ask for a location [lng, lat]
Args
msg
:str
- message text
Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html
Returns
list
- list([lat, lng])
Expand source code
def location_ask(self, msg, **kwargs): """Ask for a location [lng, lat] Args: msg (str): message text Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html Returns: list: list([lat, lng]) """ result = self.ask(self.location_msg(msg, **kwargs)) return j.data.serializers.json.loads(result)
def location_msg(self, msg, **kwargs)
-
Expand source code
def location_msg(self, msg, **kwargs): return {"category": "location_ask", "msg": msg, "kwargs": kwargs}
def md_msg(self, msg, **kwargs)
-
Expand source code
def md_msg(self, msg, **kwargs): return {"category": "md_show", "msg": msg, "kwargs": kwargs}
def md_show(self, msg, **kwargs)
-
Show markdown
Args
msg
:str
- markdown string
Expand source code
def md_show(self, msg, **kwargs): """Show markdown Args: msg (str): markdown string """ self.send_data(self.md_msg(msg, **kwargs), is_slide=True) self._queue_in.get()
def md_show_confirm(self, data, **kwargs)
-
Show a table contains the keys and values of the data dict
Args
data
:dict
- the data to be shown in the table
Expand source code
def md_show_confirm(self, data, **kwargs): """Show a table contains the keys and values of the data dict Args: data (dict): the data to be shown in the table """ if "msg" in kwargs: msg = kwargs["msg"] else: msg = "Please make sure of the entered values before starting deployment" self.send_data({"category": "confirm", "data": data, "kwargs": kwargs, "msg": msg}, is_slide=True) self._queue_in.get()
def md_show_update(self, msg, **kwargs)
-
Expand source code
def md_show_update(self, msg, **kwargs): self.send_data({"category": "infinite_loading", "msg": msg, "kwargs": kwargs}, is_slide=False)
def multi_choice(self, msg, options, **kwargs)
-
Ask for a multiple options
Args
msg
:str
- message text
Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html min_options (int): min number of selected options max_options (int): max number selected options
Returns
str
- user input
Expand source code
def multi_choice(self, msg, options, **kwargs): """Ask for a multiple options Args: msg (str): message text Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html min_options (int): min number of selected options max_options (int): max number selected options Returns: str: user input """ result = self.ask(self.multi_choice_msg(msg, options, **kwargs)) return j.data.serializers.json.loads(result)
def multi_choice_msg(self, msg, options, **kwargs)
-
Expand source code
def multi_choice_msg(self, msg, options, **kwargs): return {"category": "multi_choice", "msg": msg, "options": options, "kwargs": kwargs}
def multi_list_choice(self, msg, options, **kwargs)
-
Ask for a multiple options
Args
msg
:str
- message text
Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html min_options (int): min number of selected options max_options (int): max number selected options
Returns
str
- user input
Expand source code
def multi_list_choice(self, msg, options, **kwargs): """Ask for a multiple options Args: msg (str): message text Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html min_options (int): min number of selected options max_options (int): max number selected options Returns: str: user input """ result = self.ask(self.multi_list_choice_msg(msg, options, **kwargs)) return j.data.serializers.json.loads(result)
def multi_list_choice_msg(self, msg, options, **kwargs)
-
Expand source code
def multi_list_choice_msg(self, msg, options, **kwargs): return {"category": "multi_list_choice", "msg": msg, "options": options, "kwargs": kwargs}
def multi_values_ask(self, msg, **kwargs)
-
Ask for multiple values
Args
msg
:str
- message text
Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html
Returns
dict
- the result as a dict
Expand source code
def multi_values_ask(self, msg, **kwargs): """Ask for multiple values Args: msg (str): message text Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html Returns: dict: the result as a dict """ result = self.ask({"category": "ask_multi_values", "msg": msg, "kwargs": kwargs}) return j.data.serializers.json.loads(result)
def new_form(self)
-
Expand source code
def new_form(self): """Create a new form Returns: Form: form object """ return Form(self)
def qrcode_show(self, msg, data, scale=10, **kwargs)
-
Show QR code as an image
Args
msg
:str
- message
data
:str
- data to be encoded
scale
:int
, optional- qrcode scale. Defaults to 10.
Keyword Arguments: md (bool): render message as markdown html (bool): render message as html
Expand source code
def qrcode_show(self, msg, data, scale=10, **kwargs): """Show QR code as an image Args: msg (str): message data (str): data to be encoded scale (int, optional): qrcode scale. Defaults to 10. Keyword Arguments: md (bool): render message as markdown html (bool): render message as html """ qrcode = j.tools.qrcode.base64_get(data, scale=scale) self.send_data({"category": "qrcode_show", "msg": msg, "qrcode": qrcode, "kwargs": kwargs}, is_slide=True) self._queue_in.get()
def secret_ask(self, msg, **kwargs)
-
Ask for a secret value
Args
msg
:str
- message text
Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html min_length (int): min length max_length (int): max length
Returns
str
- user input
Expand source code
def secret_ask(self, msg, **kwargs): """Ask for a secret value Args: msg (str): message text Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html min_length (int): min length max_length (int): max length Returns: str: user input """ return self.ask(self.secret_msg(msg, **kwargs))
def secret_msg(self, msg, **kwargs)
-
Expand source code
def secret_msg(self, msg, **kwargs): return {"category": "secret_ask", "msg": msg, "kwargs": kwargs}
def send_data(self, data, is_slide=False)
-
Expand source code
def send_data(self, data, is_slide=False): data.setdefault("kwargs", {}) retry = data["kwargs"].pop("retry", False) if is_slide and not retry: self.step_info["slide"] += 1 output = {"info": self.info, "payload": data} self._last_output = output self._queue_out.put(output)
def send_error(self, message, **kwargs)
-
Expand source code
def send_error(self, message, **kwargs): self.send_data({"category": "error", "msg": message, "kwargs": kwargs}) self._queue_in.get()
def set_work(self, data)
-
Expand source code
def set_work(self, data): return self._queue_in.put(data)
def single_choice(self, msg, options, **kwargs)
-
Ask for a single option
Args
msg
:str
- message text
Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html
Returns
str
- user input
Expand source code
def single_choice(self, msg, options, **kwargs): """Ask for a single option Args: msg (str): message text Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html Returns: str: user input """ return self.ask(self.single_choice_msg(msg, options, **kwargs))
def single_choice_msg(self, msg, options, **kwargs)
-
Expand source code
def single_choice_msg(self, msg, options, **kwargs): return {"category": "single_choice", "msg": msg, "options": options, "kwargs": kwargs}
def stop(self, msg=None, **kwargs)
-
Expand source code
def stop(self, msg=None, **kwargs): raise StopChatFlow(msg=msg, **kwargs)
def string_ask(self, msg, **kwargs)
-
Ask for a string value
Args
msg
:str
- message text
Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html min_length (int): min length max_length (int): max length
Returns
str
- user input
Expand source code
def string_ask(self, msg, **kwargs): """Ask for a string value Args: msg (str): message text Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html min_length (int): min length max_length (int): max length Returns: str: user input """ return self.ask(self.string_msg(msg, **kwargs))
def string_msg(self, msg, **kwargs)
-
Expand source code
def string_msg(self, msg, **kwargs): return {"category": "string_ask", "msg": msg, "kwargs": kwargs}
def text_ask(self, msg, **kwargs)
-
Ask for a multi line string value
Args
msg
:str
- message text
Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html
Returns
str
- user input
Expand source code
def text_ask(self, msg, **kwargs): """Ask for a multi line string value Args: msg (str): message text Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html Returns: str: user input """ return self.ask(self.text_msg(msg, **kwargs))
def text_msg(self, msg, **kwargs)
-
Expand source code
def text_msg(self, msg, **kwargs): return {"category": "text_ask", "msg": msg, "kwargs": kwargs}
def time_delta_ask(self, msg, **kwargs)
-
Ask for a time delta example: 1Y 1M 1w 2d 1h
Args
msg
:str
- message text
Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html
Returns
datetime.datetime
- user input
Expand source code
def time_delta_ask(self, msg, **kwargs): """Ask for a time delta example: 1Y 1M 1w 2d 1h Args: msg (str): message text Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html Returns: datetime.datetime: user input """ result = self.ask(self.time_delta_msg(msg, timedelta=True, **kwargs)) return j.data.time.get(result).humanize()
def time_delta_msg(self, msg, **kwargs)
-
Expand source code
def time_delta_msg(self, msg, **kwargs): return {"category": "time_delta", "msg": msg, "kwargs": kwargs}
def upload_file(self, msg, **kwargs)
-
Ask for a file to be uploaded
Args
msg
:str
- message text
Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html max_size (int): file max size allowed_types: list of allowed types example : ['text/plain']
Returns
str
- file content
Expand source code
def upload_file(self, msg, **kwargs): """Ask for a file to be uploaded Args: msg (str): message text Keyword Arguments: required (bool): flag to make this field required md (bool): render message as markdown html (bool): render message as html max_size (int): file max size allowed_types: list of allowed types example : ['text/plain'] Returns: str: file content """ return self.ask(self.upload_file_msg(msg, **kwargs))
def upload_file_msg(self, msg, **kwargs)
-
Expand source code
def upload_file_msg(self, msg, **kwargs): return {"category": "upload_file", "msg": msg, "kwargs": kwargs}
def user_info(self, **kwargs)
-
Expand source code
def user_info(self, **kwargs): self.send_data({"category": "user_info", "kwargs": kwargs}) result = j.data.serializers.json.loads(self._queue_in.get()) return result
class Result (loader=builtins.str)
-
Expand source code
class Result: def __init__(self, loader=str): self._value = None self._loader = loader @property def value(self): return self._value @value.setter def value(self, value): self._value = self._loader(value)
Instance variables
var value
-
Expand source code
@property def value(self): return self._value
class StopChatFlow (msg=None, **kwargs)
-
Common base class for all non-exit exceptions.
Expand source code
class StopChatFlow(Exception): def __init__(self, msg=None, **kwargs): super().__init__(self, msg) self.msg = msg self.kwargs = kwargs
Ancestors
- builtins.Exception
- builtins.BaseException