A Redis-backed REPL that saves command history, output, & errors
Project description
Install
% pip3 install chloop
The GetCharLoop class is provided by the chloop package. Calling an instance of this class starts a REPL session, which the user can end by pressing Ctrl + d or Ctrl + c.
See the Example section below.
Usage
The first character you type at the REPL prompt is significant.
The colon
Hitting the : key at the prompt will allow you to enter a command and any arguments you need to pass to that command.
:docstrings to view docstrings of methods defined on the class
:errors to view colon commands that raised exceptions
:history view colon commands issued
:pdb to start a pdb session (debugging/inspection)
:ipython to start ipython shell
:shortcuts to view hotkey shortcuts
Any methods added to your sub-class of GetCharLoop are callable as colon commands, as long as they do not start with an underscore (_). Methods should only accept ``*args``, if anything.
For any methods/commands that should not be logged to the history, append the method name to the end of the self._DONT_LOG_CMDS list.
The dash
Hitting the - key at the prompt will allow you to type a note.
The question mark
Hitting the ? key at the prompt will display the class docstring(s) and the startup message.
Other keys
Hitting any other key at the prompt will do one of the following:
call a registered shortcut function bound to the key (use :shortcuts command to see what is available)
display the character and its integer ordinal
A hotkey can be bound to any callable object that accepts no arguments.
Use functools.partial (if necessary) to create a callable accepting no arguments.
Adding hotkeys (simple)
call the _add_hotkey method on your instance of GetCharLoop (or sub-class) with the following args
ch: character hotkey
func: callable object that accepts no arguments
help_string: a string containing short help text for hotkey
Adding hotkeys (when using callables on self)
call the self._chfunc_dict_update method in the __init__ method of your subclass with a list of tuples or a dict.
the keys of the dict (or first items in list of tuples) are the hotkey characters
the values of the dict (or second items in list of tuples) are 2-item tuples
1st item is a callable that accepts no arguments
2nd item is a short help string
Note: when passing a dict, the items will be inserted in the alphabetical order of the help string.
Basic example
% python3 -c 'from chloop import GetCharLoop; GetCharLoop()()'
> :docstrings
======================================================================
Loop forever, receiving character input from user and performing actions
- ^d or ^c to break the loop
- ':' to enter a command (and any arguments)
- the name of the command should be monkeypatched on the GetCharLoop
instance, or be a defined method on a GetCharLoop sub-class
- the function bound to `:command` should accept `*args` only
- '-' to receive an input line from user (a note)
- '?' to show the class docstring(s) and the startup message
.:: docstrings ::.
Print/return the docstrings of methods defined on this class
.:: errors ::.
Print/return any colon commands that raised exceptions (w/ traceback)
.:: history ::.
Print/return colon commands used
.:: ipython ::.
Start ipython shell. To continue back to the input loop, use 'ctrl + d'
.:: pdb ::.
Start pdb (debugger). To continue back to the input loop, use 'c'
.:: shortcuts ::.
Print/return any hotkey shortcuts defined on this class
> :pdb
[10] > /tmp/ch/venv/lib/python3.5/site-packages/chloop/__init__.py(90)__call__()
-> continue
(Pdb++) l
85 cmd = user_input.split()[0]
86 args = user_input.split()[1:]
87
88 if cmd == 'pdb':
89 import pdb; pdb.set_trace()
90 -> continue
91
92 if cmd == 'ipython':
93 from IPython import embed; embed()
94 continue
95
(Pdb++) self._collection
Collection('chloop-log', 'default', index_fields='cmd,status,error_type', json_fields='args,value')
(Pdb++) self._collection.keyspace
[]
(Pdb++) c
> :ipython
Python 3.5.1+ (default, Mar 30 2016, 22:46:26)
Type "copyright", "credits" or "license" for more information.
IPython 5.2.2 -- An enhanced Interactive Python.
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.
object? -> Details about 'object', use 'object??' for extra details.
In [1]: self._collection
Out[1]: Collection('chloop-log', 'default', index_fields='cmd,status,error_type', json_fields='args,value')
In [2]: self.shortcuts
Out[2]: <bound method GetCharLoop.shortcuts of <chloop.GetCharLoop object at 0x7f9f8ff5f5f8>>
In [3]: self.docstrings
Out[3]: <bound method GetCharLoop.docstrings of <chloop.GetCharLoop object at 0x7f9f8ff5f5f8>>
In [4]:
Do you really want to exit ([y]/n)? y
> :shortcuts
> - there are no shortcuts defined by default
>
Example (sub-class)
Import GetCharLoop and sub-class it
from functools import partial
from chloop import GetCharLoop
class Mine(GetCharLoop):
"""A sub-class of GetCharLoop"""
def __init__(self, *args, **kwargs):
# Process any extra/custom kwargs here and set some attributes
self._mything = kwargs.pop('mything', 'some default value')
super(Mine, self).__init__(*args, **kwargs)
# Add some single-key shorcuts that call methods on `self`
self._chfunc_dict_update([
('h', (self.history,
'display recent command history')),
('e', (self.errors,
'display recent errors')),
])
def somefunc(self, *args):
"""Joins the args passed to it into a string"""
args_as_one = ' '.join(args)
print(repr(args_as_one))
return args_as_one
def lame(self):
"""raise exception"""
return 1/0
Initialize the sub-class and call it
if __name__ == '__main__':
m = Mine(prompt='\nmyprompt> ')
m._add_hotkey('a', lambda: print('hello'), 'say hello')
m()
Interact with the REPL
Assuming the above code is in a file called main.py
% python main.py
myprompt> :somefunc here are some args
u'here are some args'
myprompt> :shortcuts
'e' -- display recent errors
'h' -- display recent command history
'a' -- say hello
myprompt> a
hello
myprompt> :lame
======================================================================
Traceback (most recent call last):
File "/home/ken/chloop/chloop/__init__.py", line 232, in __call__
value = cmd_func()
File "main.py", line 33, in lame
return 1/0
ZeroDivisionError: integer division or modulo by zero
cmd: u'lame'
args: []
myprompt> :pdb
...
myprompt> e
(errors output)
myprompt> - here is a note
myprompt> - here is another note
myprompt>
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file chloop-0.2.8-py3-none-any.whl.
File metadata
- Download URL: chloop-0.2.8-py3-none-any.whl
- Upload date:
- Size: 10.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9cfd878e6b685b33ade17bf66bb56176bf9f022dbbe8fbc59a535c44b89e0438
|
|
| MD5 |
8cb3028a24ee5744f6e4af878ef7b1cd
|
|
| BLAKE2b-256 |
b3a6b66628d2a51c178f685575b5b8053ec892d3ebe74aee9dfb8ba75943060d
|