щелчок python, сделать значение параметра необязательным

Я работаю над небольшим инструментом командной строки, используя Python 2. и нажмите. Мой инструмент должен либо записать значение, либо прочитать его, либо не изменять его. Было бы неплохо, если бы я мог сделать следующее:

mytool --r0=0xffff.........Установить значение r0 на 0xffff
mytool --r0.......................Прочитать значение r0
mytool. ..............................Ничего не делайте с r0

Судя по документации, это невозможно, но я мог это пропустить. Так это возможно или мне нужно найти другой подход?


person flashburn    schedule 23.11.2016    source источник
comment
@Koga Да, у меня была такая же мысль, но мне было интересно, смогу ли я сделать что-то подобное, не используя default   -  person flashburn    schedule 23.11.2016
comment
Почему вы не хотите использовать default?   -  person Koga    schedule 23.11.2016
comment
@Koga Инструмент предназначен для чтения/записи значений регистров на аппаратном уровне. Поэтому, если я дам ему значение по умолчанию, значение будет set register to a value of 1. Другими словами, вызов только mytool будет эквивалентен mytool --r0=1, что означает set register 0 to 1, что не входит в мои намерения.   -  person flashburn    schedule 23.11.2016
comment
Не работал с щелчком, но не могли бы вы использовать нецелочисленное значение по умолчанию? В чем я не уверен, так это в том, как ничего не делать, когда это не указано, но что-то, когда оно указано голым.   -  person mwchase    schedule 23.11.2016
comment
@mwchase Это была еще одна мысль, которая у меня была. Прямо сейчас я использую -2 для обозначения ничего, -1 для обозначения чтения и 0 до 0xffffffff для обозначения записи. Но я думаю, что это немного некрасиво. Скажем, я хочу прочитать r0. mytool --r0 выглядит гораздо лучше, чем mytool --r0=-1. Это просто не выглядит чистым.   -  person flashburn    schedule 23.11.2016
comment
Было бы проблематично с опцией, которая принимает «необязательный» параметр. Синтаксис командной строки может легко оказаться неоднозначным, и он не будет соответствовать соглашениям командной строки Unix. Идея @mwchase кажется хорошим решением. Вы также можете разделить его на два варианта: один логический и один со значением. Или посмотрите на использование команд вместо этого.   -  person J. P. Petersen    schedule 24.11.2016
comment
Кое-что, что только что пришло мне в голову: что произойдет, если вы прочитаете из двух регистров? Как вы форматируете это? Я не знаю точно, но, может быть, у вас должен быть флаг для чтения, который принимает регистр в качестве аргумента?   -  person mwchase    schedule 24.11.2016


Ответы (1)


Один из способов решить эту проблему — ввести еще один параметр с именем r0_set. А затем, чтобы сохранить желаемую командную строку, мы можем наследоваться от click.Command и заменить parse_args, чтобы превратить введенное пользователем r0=0xffff в r0_set=0xffff

Код:

class RegisterReaderOption(click.Option):
    """ Mark this option as getting a _set option """
    register_reader = True

class RegisterWriterOption(click.Option):
    """ Fix the help for the _set suffix """
    def get_help_record(self, ctx):
        help = super(RegisterWriterOption, self).get_help_record(ctx)
        return (help[0].replace('_set ', '='),) + help[1:]

class RegisterWriterCommand(click.Command):
    def parse_args(self, ctx, args):
        """ Translate any opt= to opt_set= as needed """
        options = [o for o in ctx.command.params
                   if getattr(o, 'register_reader', None)]
        prefixes = {p for p in sum([o.opts for o in options], [])
                    if p.startswith('--')}
        for i, a in enumerate(args):
            a = a.split('=')
            if a[0] in prefixes and len(a) > 1:
                a[0] += '_set'
                args[i] = '='.join(a)

        return super(RegisterWriterCommand, self).parse_args(ctx, args)

Тестовый код:

@click.command(cls=RegisterWriterCommand)
@click.option('--r0', cls=RegisterReaderOption, is_flag=True,
              help='Read the r0 value')
@click.option('--r0_set', cls=RegisterWriterOption,
              help='Set the r0 value')
def cli(r0, r0_set):
    click.echo('r0: {}  r0_set: {}'.format(r0, r0_set))

cli(['--r0=0xfff', '--r0'])
cli(['--help'])

Результаты:

r0: True  r0_set: 0xfff

Usage: test.py [OPTIONS]

Options:
  --r0       Read the r0 value
  --r0=TEXT  Set the r0 value
  --help     Show this message and exit.
person Stephen Rauch    schedule 23.05.2017
comment
Не является ли это решение довольно сложным, учитывая вариант использования? - person Te-jé Rodgers; 24.06.2021
comment
@ Te-jéRodgers, это менее 20 строк кода. Требовалась нестандартная командная строка, поэтому не знаю, как здесь измерять сложность. - person Stephen Rauch; 24.06.2021
comment
Тоже не работает с сегодняшнего дня. Кто знает, что изменилось в Click, но приведенный выше код не имеет никакого значения в том, как ведут себя параметры Click. - person wvxvw; 03.08.2021
comment
О, теперь я понимаю, что... на самом деле это никогда не срабатывало. Проблема здесь в том, что я даже не думал об использовании =, но потом, прочитав код, понял, что это необходимо. Кроме того, я не использовал длинные имена опций. Что ж. Это сломано слишком многими способами, чтобы быть реальным решением. - person wvxvw; 03.08.2021
comment
@wvxvw, я только что запустил этот код с помощью click 8 и python 3.8 и получил тот же результат, что и 4 года назад. Так что мне очень непонятно, к чему вы тут клоните. - person Stephen Rauch; 03.08.2021
comment
Ну, это не работает так, как предполагал ОП. Например, ваш код не работает, если используются как короткие, так и длинные имена опций, он не работает впоследствии, если короткие имена опций даны вместе или по отдельности, он не работает, когда вместо равенства используется пробел. По сути, это не работает в большинстве случаев. Он работает только иногда, возможно, наименее вероятным образом, которым он будет использоваться. - person wvxvw; 03.08.2021
comment
Наконец, справочное сообщение также неверно. Он не должен указывать это как два отдельных варианта. Это должна быть та же опция с аргументом по умолчанию. Я исследовал эту тему в системе отслеживания проблем Click, и неспособность сделать это кажется болезненной проблемой, о которой им упоминалось несколько раз, но, похоже, она не решена. github.com/pallets/click/pull/1618 должен был решить эту проблему, вместо этого , кажется, делает какую-то бесполезную ерунду. - person wvxvw; 03.08.2021
comment
@wvxvw, извините, это вас так расстраивает. Я не уверен, что ваши ожидания хорошо согласуются с реальностью свободных программ. - person Stephen Rauch; 03.08.2021
comment
Это бесплатно, когда я выбираю его использовать. Когда мне платят за то, чтобы я разбирался с этим мусором, это не бесплатно. Это платно за мусор... (Я не имею в виду ваш код. Я считаю, что вы честно пытались что-то исправить, просто не были достаточно тщательными, так как потребовалось бы слишком много усилий, чтобы заставить его работать), Click is мусор на слишком много уровней, чтобы упоминать их здесь. - person wvxvw; 03.08.2021