Hello, the only similar topic I found is:
Yet, there was no answer to the question how to make a custom bench command.
I am running latest v7 frappe/erpnext, bench 4.1.0 and by what I found on the net, I was able to write this:
frappe-bench/apps/test/test/commands/importer.py :
from __future__ import unicode_literals, absolute_import
import click
from bench.commands import bench_command
@click.command('test_importer')
@click.argument('a', None)
def test_importer(a=None):
print "hello"
if a:
print a
commands = [
test_importer
]
bench_command.add_command(test_importer)
Still I get error:
root: .... /frappe-bench# bench test_importer "a"
Usage: bench [OPTIONS] COMMAND [ARGS]...
Error: No such command "test_importer".
I also tried with no success:
bench --site site1.local test_importer "a"
bench --site site1.local test_importer --a "a"
bench --site site1.local test_importer -a "a"
bench --site site1.local test_importer
bench test_importer
I have been able to run the code by the following bench command from another file:
bench --site site1.local execute --args "a" test.importer.run
Yet I want to do it by a custom bench command, as the params in execute do not have names for input, while the custom command can give more hints for them.
Tried putting the command in the hooks.py and I got a lot of errors on bench start. I really do not know what to do here.
Tried with no success to define the custom command in apps/test/test/commands.py
Do I have to specify somewhere, which is my command file?
Can anyone give me some pointers?
Edit1:
by going deeper into frappe code, I managed to find:
click.Group(commands=commands)(prog_name='bench')
Still, No idea how to use it or should I use it.
Edit2:
Okey, so there is a connection to the First Edit, but I do not have / should not / must not use it directly.
Instead I should hook up to main function in frappe/utils/bench_helper.py
Okey, so far so good. main → get_app_groups → get_app_group → get_app_commands(app_name) function is trying to hook into every app namespace looking for module commands and getting from it commands array! So if I define my command in _init_.py of commands module of my app, that should do it?
Seems not yet, there is more I am missing.
Edit3:
So… commands in _init_.py is not an array, it is a list with object/s ? … Okey
Trying to set my commands variable to a list( set( [test_importer] ) ). Keeping in mind that the variable is in the “test” namespace and “commands” module.
And… Nope, not yet.
Edit4:
Finally! I am doing something! Too bad that the server is breaking, but still it’s a change!
So lets see what I’m doing:
apps/test/test/commands/_init_.py :
from __future__ import unicode_literals, absolute_import
import click
@click.command('test_importer')
@click.pass_context
@click.option('--site')
def test_importer(context):
print "hello"
commands = {"test_importer": test_importer}
and on bench start I get errors like this one:
Error: No such command "worker".
Usage: bench [OPTIONS] COMMAND [ARGS]...
So, I am overwriting all other commands
Edit5:
Judging by the code:
for command in getattr(app_command_module, 'commands', []):
ret[command.name] = command
commands is a list with functions? Did not know the function has .name :-/
With this I fixed the server start, but again the command does not run.
Edit6:
As revant_one bellow has pointed out, the name of the command has to be with “-” instead of “_”
# commands.py
from __future__ import unicode_literals, absolute_import
import click
@click.command('test-importer')
def test_importer():
print("hello")
commands = [test_importer]
Too bad it is not working for me. I will continue Monday.