Git Product home page Git Product logo

click-repl's People

Contributors

auvipy avatar bobwhitelock avatar brrzap avatar cool-rr avatar cosminbasca avatar decentral1se avatar edusantana avatar flacoste avatar ghostops77 avatar jm66 avatar opirko avatar srfwx avatar sscherfke avatar stianjensen avatar theazureshadow avatar toejough avatar untitaker avatar zanymonk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

click-repl's Issues

click_repl always reparses the group's options and arguments and invokes it

I'm writing a repl that looked like this:

import pathlib
from dataclasses import dataclass

import click
from click_repl import repl as click_repl


@dataclass
class MyDB:
    db_dir: pathlib.Path

   def get_entry(entry_id: int) -> str:
        # Stub for code that retrieves entry from the DB and formats it.
        return f"ENTRY {entry_id}"


@click.group(invoke_without_command=True)
@click.argument('db', type=click.Path(exists=False, file_okay=False, writable=True, readable=True, path_type=pathlib.Path))
@click.pass_context
def shell(ctx: click.Context, db: pathlib.Path) -> None:
    """Opens a shell to run commands on DB."""
    ctx.obj = MyDB(db)
    if ctx.invoked_subcommand is None:
        ctx.invoke(repl)


@shell.command()
@click.pass_context
def repl(ctx):
    click_repl(ctx)


@shell.command()
@click.argument('entry_id', type=int)
@click.pass_obj
def entry(mydb: MyDB, entry_id: int) -> None:
    """Display ENTRY_ID from the DB."""
    try:
        click.echo(mydb.get_entry(entry_id))
    except NotFound as e:
        click.secho(e, fg="red")

That code didn't work as expected. I was expecting something like this:

$ mycmd db
> entry 1
ENTRY 1

Instead, I got an exception about no command 1. Digging through the code, I discovered that "entry" is parsed as the argument to the group command, and not as the subcommand.

I also discovered that shell() will also be invoked in each subcommands invocation. My hunch is that the way click_repl dispatches to the parser isn't correct:

            with group.make_context(None, args, parent=group_ctx) as ctx:
                group.invoke(ctx)
                ctx.exit()

But I'm not familiar enough with the click API to know how we should be dispatching the subcommands. From the documentation, it seems that the proper way to delegate to a subcommand is through ctx.invoke(). But that takes a callable/command which we don't know at this point.

I was able to work around the issue by rewriting my code like this:

@click.group(invoke_without_command=True)
@click.option('--db', type=click.Path(exists=False, file_okay=False, writable=True, readable=True, path_type=pathlib.Path), help="the DB where entries are cached")
@click.pass_context
def shell(ctx: click.Context, db: pathlib.Path) -> None:
    # Only initializes ctx.obj on the first invocation. We are being called on every subcommands through click_repl
    if ctx.obj is None:
        if db is None:
            db = click.prompt("Enter the DB")
        ctx.obj = MyDB(db)
    if ctx.invoked_subcommand is None:
        ctx.invoke(repl)

Thanks,

0.1.3 release?

Is there any interest in creating a new release and making it available on pypi? Some features and bug fixes in master (history, etc) would be nice to utilize.

Some open pull requests look handy as well, e.g. (#33) ๐Ÿ˜ƒ

No completion of type=click.Choice for Options

Hi
thanks for this great library.
I'm wondering that does completion for type=click.Choice for options available?
this is my code

import click
from click_repl import repl


@click.group(invoke_without_command=True,)
@click.pass_context
def main(ctx):
    if not ctx.invoked_subcommand:
        repl(click.get_current_context())

@main.group()
def user():
    pass

@user.command()
@click.option('-type', type=click.Choice(['1', '2']))
def search(name):
    pass

if __name__ == '__main__':
    main()

I won't get completion for -type

Flag Autocompletion Not Working Past First Flag

If I have multiple possible flags for the click command, it will give me the autocomplete options for the first flag entered after the command name, but every next flag will not have any kind of autocompletion,

click-repl and click version 8-a2 (alpha version in master)

Click version 8.0 is no in early alpha state and the code for autocompletion has been committed, essentially rewriting the autocomplete functionality.

As part of this work the _bashcomplete function in click.core which is used by click-repl has been completely removed from click which causes a click application that uses click_repl and is testing with the alpha click 8 to fail in startup.

click_repl/init.py", line 6, in
import click._bashcomplete
ModuleNotFoundError: No module named 'click._bashcomplete'

This means to be compatible with click 8.0 click_repl should add code to use the new autocomplete mechanism when use with clic >= 8.0. See the following for more information.

Put click-repl on PyPI

I understand that click-repl is still new and unstable, but I think it's okay to put it on PyPI and mark it as alpha. It'll make it easier for me to reference to specific versions of it as dependencies.

click-repl does not work with Click 8.0.0 anymore

Click 8.0.0 removed an internal name which click-repl depends upon:

E.g. on Python 3.8 on macOS:

$ python -c "import click; import click_repl"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/Users/maiera/virtualenvs/pywbemtools38/lib/python3.8/site-packages/click_repl/__init__.py", line 6, in <module>
    import click._bashcomplete
ModuleNotFoundError: No module named 'click._bashcomplete'

Error when using CommandCollection

  File "/usr/local/lib/python2.7/dist-packages/click_repl/__init__.py", line 169, in repl
    available_commands = group_ctx.command.commands
AttributeError: 'CommandCollection' object has no attribute 'commands'

This is implemented as list_commands in CommandCollection: https://github.com/pallets/click/blob/master/click/core.py#L1225

list_commands is also implemented in Group: https://github.com/pallets/click/blob/master/click/core.py#L1197

This provides a consistent interface to both types.

Start showing command options before typed

My motivation for using click-repl is to make my script more discovereable for users. So it'll be nice if, when they're starting to type a command, the options for that command would show on the screen so they could choose from them, even without typing -.

Add support for new click's version autocompletion flag

As we all want arguements and options to be auto completed even if they are not the flag itself - new click versions have added a new flag to option called autocompletion which receives a function that returns a list of possible completions.

This can be seen here:
https://github.com/pallets/click/blob/master/docs/bashcomplete.rst

It can be nice to add a support for this feature as it'll allow us to have a non trivial auto completion quite quickly

Release providing argument choices

Latest release was in January and I believe was generated just before a branch was merged that supports autocompletion of argument choices (#33). I verified this with my application using v0.1.3 vs top of tree master.

It would be great to get a new official release out on pypi that includes this feature. Once 0.1.4 (or whatever) is released, I would port my app from 0.1.2 and release to my set of users.

Thanks for all the effort!

Adding tests to pypi source

Currently the tests are missing from pypi srcdist.
It would be great, if they could be included! Thanks :)

Main group with required options

I went through the README and the code but did not find a way to prevent click_repl from repeatedly asking for the main cli options.

Example:

Desired behaviour

$ mycli --user=hello c1
Executed C1!
$ mycli --user=hello
> c1
Executed C1!

With this code:

from click import group, command, option, pass_context
from click_repl import repl

@group(invoke_without_command=True)
@option('--user', prompt=True)
@pass_context
def cli(ctx, user):
    if ctx.invoked_subcommand is None:
        repl(ctx)
        ctx.exit()

@cli.command()
def c1():
    print('Executed C1!')

cli()

I get:

$ mycli --user=hello c1
Executed C1!
$ mycli --user=hello
> c1
User: <waiting for prompt>

Thanks in advance for the help

Allow exiting the click_repl from a click command

If I'm aware in click that I'm in a click_repl mode (if I have any indication that I left for myself), I want to sometimes be able to exit the click_repl from my code.

The way I think this solution can be acheived is by being able to let the ExitReplException in the the context try catch also break the loop.

Make a dev branch

Things I would like to recommend to this repo

  • Create a dev branch from master, so that everyone can add new features and improve code from here, and make updates as version 0.2.1dev0 or something (or make a pypi branch)
  • And add an another gh-actions in master that publishes the package to pypi once you've merged the code from dev branch to master branch
  • Also, I would also recommend to delete the unnecessary ci branch in this repo

Exception when entering command with args/options using python 2.7

When in the interactive mode using click_repl and a command is entered that displays possible completions using python 2.7, and prompt-toolkit > version 2.0 an exception is generated from prompt-toolkit. The exception occurs when the first space between comand and subcommands is entered.

This is not an issue with python 3.

Thus in the project pywbemcli entering a command in interactive mdoe like:

class enumerate --no
Fails with the exception on the space after class or after enumerate.

This does not happen on a corresponding command line command when click auto-completion is enabled.

This issue does not occur with prompt-toolkit 1.0 but the failure started when we changed the requirements to use prompt-toolkit >= 2..0

The following comment shows the exception.

Lag after pressing enter on empty row is too long

I launch the repl and press enter without typing anything, and I have to wait about 0.5 seconds before the next prompt appears. I tried this several times and I get the delay every time. I guess some kind of heavy thinking is performed? Maybe put in a check that if the string is empty, just show another prompt without thinking too much?

Allow typing "help" instead of ":help"

How are users supposed to figure out that they should type :help rather than help? Go to the click-repl GitHub page and read about it? I'm preparing a script for people who don't care about my script, don't care about click and definitely don't care about click-repl. I want to make the most obvious thing work for them.

Is this project still alive?

Sorry for asking so directly, but the last release was in 10/2018, and since then none of the PRs that had been provided have been answered to or merged.

Ability to autocomplete filename

would be nice to do auto complete of filenames, like ipython. if we don't want to do this in general context, maybe we can do this when specifying the value of the click file type option?

repl is not maintained after first command

I tried the example in windows10 / python3.7 and the repl exits after the first command unlike the example where you press ctrl+c to exit. Wondering if this is expected due to platform differences, and/or maybe its a quick fix using the advanced method.

C:\Users\.....> my-app.py repl
> hello
Hello!

C:\Users\.....>

click v7 breaks click_repl

click_repl works with click==6.7 but upgrading to click==7.0 breaks it. Sample code:

from __future__ import print_function
import click
import click_repl

@click.group()
def cli():
    print("in cli")

@cli.command()
def test():
    print("in test")

@cli.command()
def repl():
    click_repl.repl(click.get_current_context())

if __name__ == '__main__':
    cli()

Running with click v6.7, the repl works. With click 7.0, the repl exits after the first command.

AttributeError: 'Command' object has no attribute 'command' | Discord.py

Code:

@help.command()
async def ping(ctx):
        em = discord.Embed(
        title="Ping",
        description="This command shows your latency",
        color=0x161716
    )
    await ctx.send(embed=em)

It shows this error:
File "D:\Kunnu\Discord.py\bot.py", line 39, in
@help.command()
AttributeError: 'Command' object has no attribute 'command'

can't set `get_prompt_tokens` in `prompt_kwargs`

prompt-toolkit doesn't like it when 'message' and 'get_prompt_tokens' are both set:

    repl(click.get_current_context(), prompt_kwargs=prompt_kwargs)
[...]
  File "/tmp/build/foo/lib/python3.6/site-packages/prompt_toolkit/shortcuts.py", line 233, in create_prompt_layout
    assert not (message and get_prompt_tokens)
AssertionError

so this line prevents setting a dynamic prompt generator in prompt_kwargs.

click v7 breaks repl help

When upgrading to click==7.0 commands help are not displayed anymore. Sample code:

from __future__ import print_function
import click
import click_repl

@click.group()
def cli():
    pass

@cli.command()
def test1():
    """test 1 help"""
    print("in test 1")

@cli.command()
def test2():
    """test 2 help"""
    print("in test 2")

@cli.command()
def repl():
    click_repl.repl(click.get_current_context())

if __name__ == '__main__':
    cli()

Add automatic coloring

It'll be nice if the shell was using different colors so it'll be easier on the eyes. (e.g. one color for the prompt, one color for commands.)

History is not compatible with prompt_toolkit 2.0

Just a heads up: prompt_toolkit just released a 2.0 version. Not sure if it'll break anything else, but it broke history for us. It's possible this actually represents a bug in prompt_toolkit code rather than click-repl, but I haven't dug into it. The docs still imply that history should be a keyword argument.

We pinned our version to 1.x for now.

Here's the stack:

  File "/usr/local/lib/python2.7/site-packages/click_repl/__init__.py", line 192, in repl
    command = get_command()
  File "/usr/local/lib/python2.7/site-packages/click_repl/__init__.py", line 186, in get_command
    return prompt(**prompt_kwargs)
  File "/usr/local/lib/python2.7/site-packages/prompt_toolkit/shortcuts/prompt.py", line 793, in prompt
    return session.prompt(*a, **kw)
TypeError: prompt() got an unexpected keyword argument 'history'

Prompt character not shown via SSH

I'm doing a (simple) restricted shell around this (more for convenience than security's sake), and the prompt character doesn't show up unless I do ssh -t, which makes sense - the library doesn't know it's a valid TTY.

Can we nevertheless get a way to force a prompt character to show up?

TypeError when running readme example

Hello,

when running the readme example, it fails with :

bla@cpu:/mnt/data/code/python/quick_tests$ python3 test.py repl
Traceback (most recent call last):
File "test.py", line 15, in
cli()
File "/home/bla/.local/lib/python3.4/site-packages/click/core.py", line 700, in __call__
return self.main(_args, *_kwargs)
File "/home/bla/.local/lib/python3.4/site-packages/click/core.py", line 680, in main
rv = self.invoke(ctx)
File "/home/bla/.local/lib/python3.4/site-packages/click/core.py", line 1027, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/home/bla/.local/lib/python3.4/site-packages/click/core.py", line 873, in invoke
return ctx.invoke(self.callback, *_ctx.params)
File "/home/bla/.local/lib/python3.4/site-packages/click/core.py", line 508, in invoke
return callback(_args, *_kwargs)
File "/home/bla/.local/lib/python3.4/site-packages/click/decorators.py", line 16, in new_func
return f(get_current_context(), *args, *_kwargs)
File "/home/bla/.local/lib/python3.4/site-packages/click_repl/init.py", line 66, in cli
history = History()
TypeError: Can't instantiate abstract class History with abstract methods __getitem__, __iter__, __len__, append

I'm using python 3.4.3. I guess my problem might be similar to this one.

I understand click-repl is experimental. Do you plan to develop it further?

Thx

not working with python 3.7?

I'm not sure how to further debug, but if I run the README example the app just exits with an RC of 0.

> python hello.py repl
> pip list | ack click
click          6.7
click-repl     0.1.4
> python --version
Python 3.7.0
>

Keep group context between commands in repl 'state' ?

In my setup, it kind of makes sense to have one repl for one group with multiple commands.

In that usecase, I would like the group context (ie. options passed to the group, for all commands to use) to be kept in memory in the repl between commands... and also accessing it via a 'context' command.

Any advice on the proper way to do this without breaking click context handling ?

I am currently trying various things, as I couldn't find any documentation about that use case ( which seems quite intuitive, to me at least )

Adding LICENSE file to pypi release

Hi!

I package this for Arch Linux's [community] repository. As this is MIT licensed, I need to package the LICENSE file, but it's not in the pypi release tarball.
Can you please add it for the next release?

Click-repl tab completion does not work with help in options

It seems like tab completion does not work when one of the options has a help field?

import click
from click_repl import register_repl

@click.group()
def cli():
    pass

@cli.command()
@click.option('--test', default=1, show_default=True, help='Test help')
def hello(test):
    click.echo("Hello world!")

register_repl(cli)
cli()

Option test does not show up in tab completion, but when the help='Test help' is removed it will show up. Is this a bug?

add option to change prompt message on the go

I'm using the tool and it's great! I would like some option to change the prompt message while the repl is already running.

I would consider implementing this by loading from prompt_kwargs every while True loop, allowing the user of click_repl to edit the prompt_kwargs he passed to partial between commands and with it change running objects, if needed.

AttributeError: 'Command' object has no attribute 'commands'

In a function called from a setup tools entry point:

@click.command()
def main():
    repl(click.get_current_context(), prompt_kwargs={'history': FileHistory(HISTFILE)})

I get this error:

  File "/Users/lol/Library/Python/2.7/lib/python/site-packages/click_repl/__init__.py", line 169, in repl
    available_commands = group_ctx.command.commands
AttributeError: 'Command' object has no attribute 'commands'

If I do this:

@click.command()
@click.pass_context
def main(ctx):
    ctx.command.commands = []
    repl(ctx, prompt_kwargs={'history': FileHistory(HISTFILE)})

I get a different error, because pop is called incorrectly.

Commenting out lines 171-180 fixes the error. available_commands isn't used anywhere else, so this seems to be dead code?

    if isinstance(group_ctx.command, click.CommandCollection):
        available_commands = {
            cmd_name: cmd_obj
            for source in group_ctx.command.sources
            for cmd_name, cmd_obj in source.commands.items()
        }
    else:
        available_commands = group_ctx.command.commands
    available_commands.pop(repl_command_name, None)

Add command history

All the commands I use in the shell should be saved somewhere (a dotfile in my user directory?) and available as command history on the next time I use click-repl. At least using the up arrow, ctrl-R would be better.

Expanding env variables

Hey, nice job with this utility :) Have you been considering processing args by os.path.expandvars, so that environment variables can be expanded?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.