Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v1.13.0 tests fail with python 3.12 on Gentoo #708

Closed
ZeroChaos- opened this issue May 21, 2024 · 5 comments · Fixed by #709
Closed

v1.13.0 tests fail with python 3.12 on Gentoo #708

ZeroChaos- opened this issue May 21, 2024 · 5 comments · Fixed by #709
Labels
bug Apparent bug in liquidctl

Comments

@ZeroChaos-
Copy link

Describe the bug

tests fail:

FAILED tests/test_cli.py::test_json_list - AttributeError: 'tuple' object has no attribute 'split'
FAILED tests/test_cli.py::test_json_initialize - AttributeError: 'tuple' object has no attribute 'split'
FAILED tests/test_cli.py::test_json_status - AttributeError: 'tuple' object has no attribute 'split'

Commands executed

pytest using python 3.12

Output of all relevant commands with --debug flag

_______________________________________________________________________________________ test_json_list _______________________________________________________________________________________

main = <function main.<locals>.call_with_args at 0x70528859af20>

    def test_json_list(main):
>       code, out, _ = main('test', '--bus', 'virtual', 'list', '--json')

main       = <function main.<locals>.call_with_args at 0x70528859af20>

tests/test_cli.py:27: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
tests/test_cli.py:16: in call_with_args
    liquidctl.cli.main()
        args       = ('test', '--bus', 'virtual', 'list', '--json')
        capsys     = <_pytest.capture.CaptureFixture object at 0x70528853e300>
        monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x70528853e480>
liquidctl/cli.py:360: in main
    args = docopt(__doc__)
/usr/lib/python3.12/site-packages/docopt/__init__.py:919: in docopt
    parsed_arg_vector = parse_argv(Tokens(argv), list(options), options_first)
        argv       = ('--bus', 'virtual', 'list', '--json')
        default_help = True
        docstring  = ('liquidctl – monitor and control liquid coolers and other devices.\n'
 '\n'
 'Usage:\n'
 '  liquidctl [options] list\n'
 '  liquidctl [options] initialize [all]\n'
 '  liquidctl [options] status\n'
 '  liquidctl [options] set <channel> speed (<temperature> <percentage>) ...\n'
 '  liquidctl [options] set <channel> speed <percentage>\n'
 '  liquidctl [options] set <channel> color <mode> [<color>] ...\n'
 '  liquidctl [options] set <channel> screen <mode> [<value>]\n'
 '  liquidctl --help\n'
 '  liquidctl --version\n'
 '\n'
 'Device selection options (see: list -v):\n'
 '  -m, --match <substring>            Filter devices by description '
 'substring\n'
 '  -n, --pick <number>                Pick among many results for a given '
 'filter\n'
 '  --vendor <id>                      Filter devices by hexadecimal vendor '
 'ID\n'
 '  --product <id>                     Filter devices by hexadecimal product '
 'ID\n'
 '  --release <number>                 Filter devices by hexadecimal release '
 'number\n'
 '  --serial <number>                  Filter devices by serial number\n'
 '  --bus <bus>                        Filter devices by bus\n'
 '  --address <address>                Filter devices by address in bus\n'
 '  --usb-port <port>                  Filter devices by USB port in bus\n'
 '\n'
 'Animation options (devices/modes can support zero or more):\n'
 '  --speed <value>                    Abstract animation speed (device/mode '
 'specific)\n'
 '  --time-per-color <value>           Time to wait on each color (seconds)\n'
 '  --time-off <value>                 Time to wait with the LED turned off '
 '(seconds)\n'
 '  --alert-threshold <number>         Threshold temperature for a visual '
 'alert (°C)\n'
 '  --alert-color <color>              Color used by the visual high '
 'temperature alert\n'
 '  --direction <string>               If the pattern should move forward or '
 'backward.\n'
 '  --start-led <number>               The first led to start the effect at\n'
 "  --maximum-leds <number>            The number of LED's the effect should "
 'apply to\n'
 '\n'
 'Other device options:\n'
 '  --single-12v-ocp                   Enable single rail +12V OCP\n'
 '  --pump-mode <mode>                 Set the pump mode (certain Corsair '
 'coolers)\n'
 '  --fan-mode <channel>:<mode>[,...]  Set the mode for each fan (certain '
 'Corsair devices)\n'
 '  --temperature-sensor <number>      The temperature sensor number for the '
 'Commander Pro\n'
 '  --legacy-690lc                     Use Asetek 690LC in legacy mode (old '
 'Krakens)\n'
 '  --non-volatile                     Store on non-volatile controller '
 'memory\n'
 '  --direct-access                    Directly access the device despite '
 'kernel drivers\n'
 '  --unsafe <features>                Comma-separated bleeding-edge features '
 'to enable\n'
 '\n'
 'Other interface options:\n'
 '  -v, --verbose                      Output additional information\n'
 '  -g, --debug                        Show debug information on stderr\n'
 '  --json                             JSON output '
 '(list/initialization/status)\n'
 '  --version                          Display the version number\n'
 '  --help                             Show this message\n'
 '\n'
 'Deprecated:\n'
 '  -d, --device <index>           Select device by listing index\n'
 '\n'
 'Copyright 2018–2023 Jonas Malaco, Marshall Asch, CaseySJ, Tom Frey, Andrew\n'
 'Robertson, ParkerMc, Aleksa Savic, Shady Nawara and contributors\n'
 '\n'
 'Some modules also incorporate or use as reference work by leaty, Ksenija\n'
 'Stanojevic, Alexander Tong, Jens Neumaier, Kristóf Jakab, Sean Nelson, '
 'Chris\n'
 'Griffith, notaz, realies and Thomas Pircher. This is mentioned in the '
 'module\n'
 'docstring, along with appropriate additional copyright notices.\n'
 '\n'
 'SPDX-License-Identifier: GPL-3.0-or-later\n'
 '\n'
 'This program is distributed in the hope that it will be useful, but WITHOUT '
 'ANY\n'
 'WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS '
 'FOR A\n'
 'PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n')
        options    = [Option('-m', '--match', 1, None),
 Option('-n', '--pick', 1, None),
 Option(None, '--vendor', 1, None),
 Option(None, '--product', 1, None),
 Option(None, '--release', 1, None),
 Option(None, '--serial', 1, None),
 Option(None, '--bus', 1, None),
 Option(None, '--address', 1, None),
 Option(None, '--usb-port', 1, None),
 Option(None, '--speed', 1, None),
 Option(None, '--time-per-color', 1, None),
 Option(None, '--time-off', 1, None),
 Option(None, '--alert-threshold', 1, None),
 Option(None, '--alert-color', 1, None),
 Option(None, '--direction', 1, None),
 Option(None, '--start-led', 1, None),
 Option(None, '--maximum-leds', 1, None),
 Option(None, '--single-12v-ocp', 0, False),
 Option(None, '--pump-mode', 1, None),
 Option(None, '--fan-mode', 1, None),
 Option(None, '--temperature-sensor', 1, None),
 Option(None, '--legacy-690lc', 0, False),
 Option(None, '--non-volatile', 0, False),
 Option(None, '--direct-access', 0, False),
 Option(None, '--unsafe', 1, None),
 Option('-v', '--verbose', 0, False),
 Option('-g', '--debug', 0, False),
 Option(None, '--json', 0, False),
 Option(None, '--version', 0, False),
 Option(None, '--help', 0, False),
 Option('-d', '--device', 1, None)]
        options_first = False
        options_shortcut = OptionsShortcut(Option('-m', '--match', 1, None), Option('-n', '--pick', 1, None), Option(None, '--vendor', 1, None), Option(None, '--product', 1, None), Option(None, '--release', 1, None), Option(None, '--serial', 1, None), Option(None, '--bus', 1, None), Option(None, '--address', 1, None), Option(None, '--usb-port', 1, None), Option(None, '--speed', 1, None), Option(None, '--time-per-color', 1, None), Option(None, '--time-off', 1, None), Option(None, '--alert-threshold', 1, None), Option(None, '--alert-color', 1, None), Option(None, '--direction', 1, None), Option(None, '--start-led', 1, None), Option(None, '--maximum-leds', 1, None), Option(None, '--single-12v-ocp', 0, False), Option(None, '--pump-mode', 1, None), Option(None, '--fan-mode', 1, None), Option(None, '--temperature-sensor', 1, None), Option(None, '--legacy-690lc', 0, False), Option(None, '--non-volatile', 0, False), Option(None, '--direct-access', 0, False), Option(None, '--unsafe', 1, None), Option('-v', '--verbose', 0, False), Option('-g', '--debug', 0, False), Option(None, '--json', 0, False), Option('-d', '--device', 1, None))
        pattern    = Required(Either(Required(NotRequired(OptionsShortcut(Option('-m', '--match', 1, None), Option('-n', '--pick', 1, None), Option(None, '--vendor', 1, None), Option(None, '--product', 1, None), Option(None, '--release', 1, None), Option(None, '--serial', 1, None), Option(None, '--bus', 1, None), Option(None, '--address', 1, None), Option(None, '--usb-port', 1, None), Option(None, '--speed', 1, None), Option(None, '--time-per-color', 1, None), Option(None, '--time-off', 1, None), Option(None, '--alert-threshold', 1, None), Option(None, '--alert-color', 1, None), Option(None, '--direction', 1, None), Option(None, '--start-led', 1, None), Option(None, '--maximum-leds', 1, None), Option(None, '--single-12v-ocp', 0, False), Option(None, '--pump-mode', 1, None), Option(None, '--fan-mode', 1, None), Option(None, '--temperature-sensor', 1, None), Option(None, '--legacy-690lc', 0, False), Option(None, '--non-volatile', 0, False), Option(None, '--direct-access', 0, False), Option(None, '--unsafe', 1, None), Option('-v', '--verbose', 0, False), Option('-g', '--debug', 0, False), Option(None, '--json', 0, False), Option('-d', '--device', 1, None))), Command('list', False)), Required(NotRequired(OptionsShortcut(Option('-m', '--match', 1, None), Option('-n', '--pick', 1, None), Option(None, '--vendor', 1, None), Option(None, '--product', 1, None), Option(None, '--release', 1, None), Option(None, '--serial', 1, None), Option(None, '--bus', 1, None), Option(None, '--address', 1, None), Option(None, '--usb-port', 1, None), Option(None, '--speed', 1, None), Option(None, '--time-per-color', 1, None), Option(None, '--time-off', 1, None), Option(None, '--alert-threshold', 1, None), Option(None, '--alert-color', 1, None), Option(None, '--direction', 1, None), Option(None, '--start-led', 1, None), Option(None, '--maximum-leds', 1, None), Option(None, '--single-12v-ocp', 0, False), Option(None, '--pump-mode', 1, None), Option(None, '--fan-mode', 1, None), Option(None, '--temperature-sensor', 1, None), Option(None, '--legacy-690lc', 0, False), Option(None, '--non-volatile', 0, False), Option(None, '--direct-access', 0, False), Option(None, '--unsafe', 1, None), Option('-v', '--verbose', 0, False), Option('-g', '--debug', 0, False), Option(None, '--json', 0, False), Option('-d', '--device', 1, None))), Command('initialize', False), NotRequired(Command('all', False))), Required(NotRequired(OptionsShortcut(Option('-m', '--match', 1, None), Option('-n', '--pick', 1, None), Option(None, '--vendor', 1, None), Option(None, '--product', 1, None), Option(None, '--release', 1, None), Option(None, '--serial', 1, None), Option(None, '--bus', 1, None), Option(None, '--address', 1, None), Option(None, '--usb-port', 1, None), Option(None, '--speed', 1, None), Option(None, '--time-per-color', 1, None), Option(None, '--time-off', 1, None), Option(None, '--alert-threshold', 1, None), Option(None, '--alert-color', 1, None), Option(None, '--direction', 1, None), Option(None, '--start-led', 1, None), Option(None, '--maximum-leds', 1, None), Option(None, '--single-12v-ocp', 0, False), Option(None, '--pump-mode', 1, None), Option(None, '--fan-mode', 1, None), Option(None, '--temperature-sensor', 1, None), Option(None, '--legacy-690lc', 0, False), Option(None, '--non-volatile', 0, False), Option(None, '--direct-access', 0, False), Option(None, '--unsafe', 1, None), Option('-v', '--verbose', 0, False), Option('-g', '--debug', 0, False), Option(None, '--json', 0, False), Option('-d', '--device', 1, None))), Command('status', False)), Required(NotRequired(OptionsShortcut(Option('-m', '--match', 1, None), Option('-n', '--pick', 1, None), Option(None, '--vendor', 1, None), Option(None, '--product', 1, None), Option(None, '--release', 1, None), Option(None, '--serial', 1, None), Option(None, '--bus', 1, None), Option(None, '--address', 1, None), Option(None, '--usb-port', 1, None), Option(None, '--speed', 1, None), Option(None, '--time-per-color', 1, None), Option(None, '--time-off', 1, None), Option(None, '--alert-threshold', 1, None), Option(None, '--alert-color', 1, None), Option(None, '--direction', 1, None), Option(None, '--start-led', 1, None), Option(None, '--maximum-leds', 1, None), Option(None, '--single-12v-ocp', 0, False), Option(None, '--pump-mode', 1, None), Option(None, '--fan-mode', 1, None), Option(None, '--temperature-sensor', 1, None), Option(None, '--legacy-690lc', 0, False), Option(None, '--non-volatile', 0, False), Option(None, '--direct-access', 0, False), Option(None, '--unsafe', 1, None), Option('-v', '--verbose', 0, False), Option('-g', '--debug', 0, False), Option(None, '--json', 0, False), Option('-d', '--device', 1, None))), Command('set', False), Argument('<channel>', None), Command('speed', False), OneOrMore(Required(Argument('<temperature>', None), Argument('<percentage>', None)))), Required(NotRequired(OptionsShortcut(Option('-m', '--match', 1, None), Option('-n', '--pick', 1, None), Option(None, '--vendor', 1, None), Option(None, '--product', 1, None), Option(None, '--release', 1, None), Option(None, '--serial', 1, None), Option(None, '--bus', 1, None), Option(None, '--address', 1, None), Option(None, '--usb-port', 1, None), Option(None, '--speed', 1, None), Option(None, '--time-per-color', 1, None), Option(None, '--time-off', 1, None), Option(None, '--alert-threshold', 1, None), Option(None, '--alert-color', 1, None), Option(None, '--direction', 1, None), Option(None, '--start-led', 1, None), Option(None, '--maximum-leds', 1, None), Option(None, '--single-12v-ocp', 0, False), Option(None, '--pump-mode', 1, None), Option(None, '--fan-mode', 1, None), Option(None, '--temperature-sensor', 1, None), Option(None, '--legacy-690lc', 0, False), Option(None, '--non-volatile', 0, False), Option(None, '--direct-access', 0, False), Option(None, '--unsafe', 1, None), Option('-v', '--verbose', 0, False), Option('-g', '--debug', 0, False), Option(None, '--json', 0, False), Option('-d', '--device', 1, None))), Command('set', False), Argument('<channel>', None), Command('speed', False), Argument('<percentage>', None)), Required(NotRequired(OptionsShortcut(Option('-m', '--match', 1, None), Option('-n', '--pick', 1, None), Option(None, '--vendor', 1, None), Option(None, '--product', 1, None), Option(None, '--release', 1, None), Option(None, '--serial', 1, None), Option(None, '--bus', 1, None), Option(None, '--address', 1, None), Option(None, '--usb-port', 1, None), Option(None, '--speed', 1, None), Option(None, '--time-per-color', 1, None), Option(None, '--time-off', 1, None), Option(None, '--alert-threshold', 1, None), Option(None, '--alert-color', 1, None), Option(None, '--direction', 1, None), Option(None, '--start-led', 1, None), Option(None, '--maximum-leds', 1, None), Option(None, '--single-12v-ocp', 0, False), Option(None, '--pump-mode', 1, None), Option(None, '--fan-mode', 1, None), Option(None, '--temperature-sensor', 1, None), Option(None, '--legacy-690lc', 0, False), Option(None, '--non-volatile', 0, False), Option(None, '--direct-access', 0, False), Option(None, '--unsafe', 1, None), Option('-v', '--verbose', 0, False), Option('-g', '--debug', 0, False), Option(None, '--json', 0, False), Option('-d', '--device', 1, None))), Command('set', False), Argument('<channel>', None), Command('color', False), Argument('<mode>', None), OneOrMore(NotRequired(Argument('<color>', None)))), Required(NotRequired(OptionsShortcut(Option('-m', '--match', 1, None), Option('-n', '--pick', 1, None), Option(None, '--vendor', 1, None), Option(None, '--product', 1, None), Option(None, '--release', 1, None), Option(None, '--serial', 1, None), Option(None, '--bus', 1, None), Option(None, '--address', 1, None), Option(None, '--usb-port', 1, None), Option(None, '--speed', 1, None), Option(None, '--time-per-color', 1, None), Option(None, '--time-off', 1, None), Option(None, '--alert-threshold', 1, None), Option(None, '--alert-color', 1, None), Option(None, '--direction', 1, None), Option(None, '--start-led', 1, None), Option(None, '--maximum-leds', 1, None), Option(None, '--single-12v-ocp', 0, False), Option(None, '--pump-mode', 1, None), Option(None, '--fan-mode', 1, None), Option(None, '--temperature-sensor', 1, None), Option(None, '--legacy-690lc', 0, False), Option(None, '--non-volatile', 0, False), Option(None, '--direct-access', 0, False), Option(None, '--unsafe', 1, None), Option('-v', '--verbose', 0, False), Option('-g', '--debug', 0, False), Option(None, '--json', 0, False), Option('-d', '--device', 1, None))), Command('set', False), Argument('<channel>', None), Command('screen', False), Argument('<mode>', None), NotRequired(Argument('<value>', None))), Required(Option(None, '--help', 0, False)), Required(Option(None, '--version', 0, False))))
        pattern_options = {Option(None, '--version', 0, False), Option(None, '--help', 0, False)}
        sections   = DocSections(before_usage='liquidctl – monitor and control liquid coolers and other devices.\n\n', usage_header='Usage:', usage_body='\n  liquidctl [options] list\n  liquidctl [options] initialize [all]\n  liquidctl [options] status\n  liquidctl [options] set <channel> speed (<temperature> <percentage>) ...\n  liquidctl [options] set <channel> speed <percentage>\n  liquidctl [options] set <channel> color <mode> [<color>] ...\n  liquidctl [options] set <channel> screen <mode> [<value>]\n  liquidctl --help\n  liquidctl --version\n', after_usage="\nDevice selection options (see: list -v):\n  -m, --match <substring>            Filter devices by description substring\n  -n, --pick <number>                Pick among many results for a given filter\n  --vendor <id>                      Filter devices by hexadecimal vendor ID\n  --product <id>                     Filter devices by hexadecimal product ID\n  --release <number>                 Filter devices by hexadecimal release number\n  --serial <number>                  Filter devices by serial number\n  --bus <bus>                        Filter devices by bus\n  --address <address>                Filter devices by address in bus\n  --usb-port <port>                  Filter devices by USB port in bus\n\nAnimation options (devices/modes can support zero or more):\n  --speed <value>                    Abstract animation speed (device/mode specific)\n  --time-per-color <value>           Time to wait on each color (seconds)\n  --time-off <value>                 Time to wait with the LED turned off (seconds)\n  --alert-threshold <number>         Threshold temperature for a visual alert (°C)\n  --alert-color <color>              Color used by the visual high temperature alert\n  --direction <string>               If the pattern should move forward or backward.\n  --start-led <number>               The first led to start the effect at\n  --maximum-leds <number>            The number of LED's the effect should apply to\n\nOther device options:\n  --single-12v-ocp                   Enable single rail +12V OCP\n  --pump-mode <mode>                 Set the pump mode (certain Corsair coolers)\n  --fan-mode <channel>:<mode>[,...]  Set the mode for each fan (certain Corsair devices)\n  --temperature-sensor <number>      The temperature sensor number for the Commander Pro\n  --legacy-690lc                     Use Asetek 690LC in legacy mode (old Krakens)\n  --non-volatile                     Store on non-volatile controller memory\n  --direct-access                    Directly access the device despite kernel drivers\n  --unsafe <features>                Comma-separated bleeding-edge features to enable\n\nOther interface options:\n  -v, --verbose                      Output additional information\n  -g, --debug                        Show debug information on stderr\n  --json                             JSON output (list/initialization/status)\n  --version                          Display the version number\n  --help                             Show this message\n\nDeprecated:\n  -d, --device <index>           Select device by listing index\n\nCopyright 2018–2023 Jonas Malaco, Marshall Asch, CaseySJ, Tom Frey, Andrew\nRobertson, ParkerMc, Aleksa Savic, Shady Nawara and contributors\n\nSome modules also incorporate or use as reference work by leaty, Ksenija\nStanojevic, Alexander Tong, Jens Neumaier, Kristóf Jakab, Sean Nelson, Chris\nGriffith, notaz, realies and Thomas Pircher. This is mentioned in the module\ndocstring, along with appropriate additional copyright notices.\n\nSPDX-License-Identifier: GPL-3.0-or-later\n\nThis program is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A\nPARTICULAR PURPOSE.  See the GNU General Public License for more details.\n")
        version    = None
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = [], source = ('--bus', 'virtual', 'list', '--json'), error = <class 'docopt.DocoptExit'>

    def __init__(
        self,
        source: list[str] | str,
        error: Type[DocoptExit] | Type[DocoptLanguageError] = DocoptExit,
    ) -> None:
        if isinstance(source, list):
            self += source
        else:
>           self += source.split()
E           AttributeError: 'tuple' object has no attribute 'split'

error      = <class 'docopt.DocoptExit'>
self       = []
source     = ('--bus', 'virtual', 'list', '--json')

/usr/lib/python3.12/site-packages/docopt/__init__.py:413: AttributeError
____________________________________________________________________________________ test_json_initialize ____________________________________________________________________________________

main = <function main.<locals>.call_with_args at 0x70528859b600>

    def test_json_initialize(main):
>       code, out, _ = main('test', '--bus', 'virtual', 'initialize', '--json')

main       = <function main.<locals>.call_with_args at 0x70528859b600>

tests/test_cli.py:49: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
tests/test_cli.py:16: in call_with_args
    liquidctl.cli.main()
        args       = ('test', '--bus', 'virtual', 'initialize', '--json')
        capsys     = <_pytest.capture.CaptureFixture object at 0x7052884e6810>
        monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x7052884e6990>
liquidctl/cli.py:360: in main
    args = docopt(__doc__)
/usr/lib/python3.12/site-packages/docopt/__init__.py:919: in docopt
    parsed_arg_vector = parse_argv(Tokens(argv), list(options), options_first)
        argv       = ('--bus', 'virtual', 'initialize', '--json')
        default_help = True
        docstring  = ('liquidctl – monitor and control liquid coolers and other devices.\n'
 '\n'
 'Usage:\n'
 '  liquidctl [options] list\n'
 '  liquidctl [options] initialize [all]\n'
 '  liquidctl [options] status\n'
 '  liquidctl [options] set <channel> speed (<temperature> <percentage>) ...\n'
 '  liquidctl [options] set <channel> speed <percentage>\n'
 '  liquidctl [options] set <channel> color <mode> [<color>] ...\n'
 '  liquidctl [options] set <channel> screen <mode> [<value>]\n'
 '  liquidctl --help\n'
 '  liquidctl --version\n'
 '\n'
 'Device selection options (see: list -v):\n'
 '  -m, --match <substring>            Filter devices by description '
 'substring\n'
 '  -n, --pick <number>                Pick among many results for a given '
 'filter\n'
 '  --vendor <id>                      Filter devices by hexadecimal vendor '
 'ID\n'
 '  --product <id>                     Filter devices by hexadecimal product '
 'ID\n'
 '  --release <number>                 Filter devices by hexadecimal release '
 'number\n'
 '  --serial <number>                  Filter devices by serial number\n'
 '  --bus <bus>                        Filter devices by bus\n'
 '  --address <address>                Filter devices by address in bus\n'
 '  --usb-port <port>                  Filter devices by USB port in bus\n'
 '\n'
 'Animation options (devices/modes can support zero or more):\n'
 '  --speed <value>                    Abstract animation speed (device/mode '
 'specific)\n'
 '  --time-per-color <value>           Time to wait on each color (seconds)\n'
 '  --time-off <value>                 Time to wait with the LED turned off '
 '(seconds)\n'
 '  --alert-threshold <number>         Threshold temperature for a visual '
 'alert (°C)\n'
 '  --alert-color <color>              Color used by the visual high '
 'temperature alert\n'
 '  --direction <string>               If the pattern should move forward or '
 'backward.\n'
 '  --start-led <number>               The first led to start the effect at\n'
 "  --maximum-leds <number>            The number of LED's the effect should "
 'apply to\n'
 '\n'
 'Other device options:\n'
 '  --single-12v-ocp                   Enable single rail +12V OCP\n'
 '  --pump-mode <mode>                 Set the pump mode (certain Corsair '
 'coolers)\n'
 '  --fan-mode <channel>:<mode>[,...]  Set the mode for each fan (certain '
 'Corsair devices)\n'
 '  --temperature-sensor <number>      The temperature sensor number for the '
 'Commander Pro\n'
 '  --legacy-690lc                     Use Asetek 690LC in legacy mode (old '
 'Krakens)\n'
 '  --non-volatile                     Store on non-volatile controller '
 'memory\n'
 '  --direct-access                    Directly access the device despite '
 'kernel drivers\n'
 '  --unsafe <features>                Comma-separated bleeding-edge features '
 'to enable\n'
 '\n'
 'Other interface options:\n'
 '  -v, --verbose                      Output additional information\n'
 '  -g, --debug                        Show debug information on stderr\n'
 '  --json                             JSON output '
 '(list/initialization/status)\n'
 '  --version                          Display the version number\n'
 '  --help                             Show this message\n'
 '\n'
 'Deprecated:\n'
 '  -d, --device <index>           Select device by listing index\n'
 '\n'
 'Copyright 2018–2023 Jonas Malaco, Marshall Asch, CaseySJ, Tom Frey, Andrew\n'
 'Robertson, ParkerMc, Aleksa Savic, Shady Nawara and contributors\n'
 '\n'
 'Some modules also incorporate or use as reference work by leaty, Ksenija\n'
 'Stanojevic, Alexander Tong, Jens Neumaier, Kristóf Jakab, Sean Nelson, '
 'Chris\n'
 'Griffith, notaz, realies and Thomas Pircher. This is mentioned in the '
 'module\n'
 'docstring, along with appropriate additional copyright notices.\n'
 '\n'
 'SPDX-License-Identifier: GPL-3.0-or-later\n'
 '\n'
 'This program is distributed in the hope that it will be useful, but WITHOUT '
 'ANY\n'
 'WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS '
 'FOR A\n'
 'PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n')
        options    = [Option('-m', '--match', 1, None),
 Option('-n', '--pick', 1, None),
 Option(None, '--vendor', 1, None),
 Option(None, '--product', 1, None),
 Option(None, '--release', 1, None),
 Option(None, '--serial', 1, None),
 Option(None, '--bus', 1, None),
 Option(None, '--address', 1, None),
 Option(None, '--usb-port', 1, None),
 Option(None, '--speed', 1, None),
 Option(None, '--time-per-color', 1, None),
 Option(None, '--time-off', 1, None),
 Option(None, '--alert-threshold', 1, None),
 Option(None, '--alert-color', 1, None),
 Option(None, '--direction', 1, None),
 Option(None, '--start-led', 1, None),
 Option(None, '--maximum-leds', 1, None),
 Option(None, '--single-12v-ocp', 0, False),
 Option(None, '--pump-mode', 1, None),
 Option(None, '--fan-mode', 1, None),
 Option(None, '--temperature-sensor', 1, None),
 Option(None, '--legacy-690lc', 0, False),
 Option(None, '--non-volatile', 0, False),
 Option(None, '--direct-access', 0, False),
 Option(None, '--unsafe', 1, None),
 Option('-v', '--verbose', 0, False),
 Option('-g', '--debug', 0, False),
 Option(None, '--json', 0, False),
 Option(None, '--version', 0, False),
 Option(None, '--help', 0, False),
 Option('-d', '--device', 1, None)]
        options_first = False
        options_shortcut = OptionsShortcut(Option('-m', '--match', 1, None), Option('-n', '--pick', 1, None), Option(None, '--vendor', 1, None), Option(None, '--product', 1, None), Option(None, '--release', 1, None), Option(None, '--serial', 1, None), Option(None, '--bus', 1, None), Option(None, '--address', 1, None), Option(None, '--usb-port', 1, None), Option(None, '--speed', 1, None), Option(None, '--time-per-color', 1, None), Option(None, '--time-off', 1, None), Option(None, '--alert-threshold', 1, None), Option(None, '--alert-color', 1, None), Option(None, '--direction', 1, None), Option(None, '--start-led', 1, None), Option(None, '--maximum-leds', 1, None), Option(None, '--single-12v-ocp', 0, False), Option(None, '--pump-mode', 1, None), Option(None, '--fan-mode', 1, None), Option(None, '--temperature-sensor', 1, None), Option(None, '--legacy-690lc', 0, False), Option(None, '--non-volatile', 0, False), Option(None, '--direct-access', 0, False), Option(None, '--unsafe', 1, None), Option('-v', '--verbose', 0, False), Option('-g', '--debug', 0, False), Option(None, '--json', 0, False), Option('-d', '--device', 1, None))
        pattern    = Required(Either(Required(NotRequired(OptionsShortcut(Option('-m', '--match', 1, None), Option('-n', '--pick', 1, None), Option(None, '--vendor', 1, None), Option(None, '--product', 1, None), Option(None, '--release', 1, None), Option(None, '--serial', 1, None), Option(None, '--bus', 1, None), Option(None, '--address', 1, None), Option(None, '--usb-port', 1, None), Option(None, '--speed', 1, None), Option(None, '--time-per-color', 1, None), Option(None, '--time-off', 1, None), Option(None, '--alert-threshold', 1, None), Option(None, '--alert-color', 1, None), Option(None, '--direction', 1, None), Option(None, '--start-led', 1, None), Option(None, '--maximum-leds', 1, None), Option(None, '--single-12v-ocp', 0, False), Option(None, '--pump-mode', 1, None), Option(None, '--fan-mode', 1, None), Option(None, '--temperature-sensor', 1, None), Option(None, '--legacy-690lc', 0, False), Option(None, '--non-volatile', 0, False), Option(None, '--direct-access', 0, False), Option(None, '--unsafe', 1, None), Option('-v', '--verbose', 0, False), Option('-g', '--debug', 0, False), Option(None, '--json', 0, False), Option('-d', '--device', 1, None))), Command('list', False)), Required(NotRequired(OptionsShortcut(Option('-m', '--match', 1, None), Option('-n', '--pick', 1, None), Option(None, '--vendor', 1, None), Option(None, '--product', 1, None), Option(None, '--release', 1, None), Option(None, '--serial', 1, None), Option(None, '--bus', 1, None), Option(None, '--address', 1, None), Option(None, '--usb-port', 1, None), Option(None, '--speed', 1, None), Option(None, '--time-per-color', 1, None), Option(None, '--time-off', 1, None), Option(None, '--alert-threshold', 1, None), Option(None, '--alert-color', 1, None), Option(None, '--direction', 1, None), Option(None, '--start-led', 1, None), Option(None, '--maximum-leds', 1, None), Option(None, '--single-12v-ocp', 0, False), Option(None, '--pump-mode', 1, None), Option(None, '--fan-mode', 1, None), Option(None, '--temperature-sensor', 1, None), Option(None, '--legacy-690lc', 0, False), Option(None, '--non-volatile', 0, False), Option(None, '--direct-access', 0, False), Option(None, '--unsafe', 1, None), Option('-v', '--verbose', 0, False), Option('-g', '--debug', 0, False), Option(None, '--json', 0, False), Option('-d', '--device', 1, None))), Command('initialize', False), NotRequired(Command('all', False))), Required(NotRequired(OptionsShortcut(Option('-m', '--match', 1, None), Option('-n', '--pick', 1, None), Option(None, '--vendor', 1, None), Option(None, '--product', 1, None), Option(None, '--release', 1, None), Option(None, '--serial', 1, None), Option(None, '--bus', 1, None), Option(None, '--address', 1, None), Option(None, '--usb-port', 1, None), Option(None, '--speed', 1, None), Option(None, '--time-per-color', 1, None), Option(None, '--time-off', 1, None), Option(None, '--alert-threshold', 1, None), Option(None, '--alert-color', 1, None), Option(None, '--direction', 1, None), Option(None, '--start-led', 1, None), Option(None, '--maximum-leds', 1, None), Option(None, '--single-12v-ocp', 0, False), Option(None, '--pump-mode', 1, None), Option(None, '--fan-mode', 1, None), Option(None, '--temperature-sensor', 1, None), Option(None, '--legacy-690lc', 0, False), Option(None, '--non-volatile', 0, False), Option(None, '--direct-access', 0, False), Option(None, '--unsafe', 1, None), Option('-v', '--verbose', 0, False), Option('-g', '--debug', 0, False), Option(None, '--json', 0, False), Option('-d', '--device', 1, None))), Command('status', False)), Required(NotRequired(OptionsShortcut(Option('-m', '--match', 1, None), Option('-n', '--pick', 1, None), Option(None, '--vendor', 1, None), Option(None, '--product', 1, None), Option(None, '--release', 1, None), Option(None, '--serial', 1, None), Option(None, '--bus', 1, None), Option(None, '--address', 1, None), Option(None, '--usb-port', 1, None), Option(None, '--speed', 1, None), Option(None, '--time-per-color', 1, None), Option(None, '--time-off', 1, None), Option(None, '--alert-threshold', 1, None), Option(None, '--alert-color', 1, None), Option(None, '--direction', 1, None), Option(None, '--start-led', 1, None), Option(None, '--maximum-leds', 1, None), Option(None, '--single-12v-ocp', 0, False), Option(None, '--pump-mode', 1, None), Option(None, '--fan-mode', 1, None), Option(None, '--temperature-sensor', 1, None), Option(None, '--legacy-690lc', 0, False), Option(None, '--non-volatile', 0, False), Option(None, '--direct-access', 0, False), Option(None, '--unsafe', 1, None), Option('-v', '--verbose', 0, False), Option('-g', '--debug', 0, False), Option(None, '--json', 0, False), Option('-d', '--device', 1, None))), Command('set', False), Argument('<channel>', None), Command('speed', False), OneOrMore(Required(Argument('<temperature>', None), Argument('<percentage>', None)))), Required(NotRequired(OptionsShortcut(Option('-m', '--match', 1, None), Option('-n', '--pick', 1, None), Option(None, '--vendor', 1, None), Option(None, '--product', 1, None), Option(None, '--release', 1, None), Option(None, '--serial', 1, None), Option(None, '--bus', 1, None), Option(None, '--address', 1, None), Option(None, '--usb-port', 1, None), Option(None, '--speed', 1, None), Option(None, '--time-per-color', 1, None), Option(None, '--time-off', 1, None), Option(None, '--alert-threshold', 1, None), Option(None, '--alert-color', 1, None), Option(None, '--direction', 1, None), Option(None, '--start-led', 1, None), Option(None, '--maximum-leds', 1, None), Option(None, '--single-12v-ocp', 0, False), Option(None, '--pump-mode', 1, None), Option(None, '--fan-mode', 1, None), Option(None, '--temperature-sensor', 1, None), Option(None, '--legacy-690lc', 0, False), Option(None, '--non-volatile', 0, False), Option(None, '--direct-access', 0, False), Option(None, '--unsafe', 1, None), Option('-v', '--verbose', 0, False), Option('-g', '--debug', 0, False), Option(None, '--json', 0, False), Option('-d', '--device', 1, None))), Command('set', False), Argument('<channel>', None), Command('speed', False), Argument('<percentage>', None)), Required(NotRequired(OptionsShortcut(Option('-m', '--match', 1, None), Option('-n', '--pick', 1, None), Option(None, '--vendor', 1, None), Option(None, '--product', 1, None), Option(None, '--release', 1, None), Option(None, '--serial', 1, None), Option(None, '--bus', 1, None), Option(None, '--address', 1, None), Option(None, '--usb-port', 1, None), Option(None, '--speed', 1, None), Option(None, '--time-per-color', 1, None), Option(None, '--time-off', 1, None), Option(None, '--alert-threshold', 1, None), Option(None, '--alert-color', 1, None), Option(None, '--direction', 1, None), Option(None, '--start-led', 1, None), Option(None, '--maximum-leds', 1, None), Option(None, '--single-12v-ocp', 0, False), Option(None, '--pump-mode', 1, None), Option(None, '--fan-mode', 1, None), Option(None, '--temperature-sensor', 1, None), Option(None, '--legacy-690lc', 0, False), Option(None, '--non-volatile', 0, False), Option(None, '--direct-access', 0, False), Option(None, '--unsafe', 1, None), Option('-v', '--verbose', 0, False), Option('-g', '--debug', 0, False), Option(None, '--json', 0, False), Option('-d', '--device', 1, None))), Command('set', False), Argument('<channel>', None), Command('color', False), Argument('<mode>', None), OneOrMore(NotRequired(Argument('<color>', None)))), Required(NotRequired(OptionsShortcut(Option('-m', '--match', 1, None), Option('-n', '--pick', 1, None), Option(None, '--vendor', 1, None), Option(None, '--product', 1, None), Option(None, '--release', 1, None), Option(None, '--serial', 1, None), Option(None, '--bus', 1, None), Option(None, '--address', 1, None), Option(None, '--usb-port', 1, None), Option(None, '--speed', 1, None), Option(None, '--time-per-color', 1, None), Option(None, '--time-off', 1, None), Option(None, '--alert-threshold', 1, None), Option(None, '--alert-color', 1, None), Option(None, '--direction', 1, None), Option(None, '--start-led', 1, None), Option(None, '--maximum-leds', 1, None), Option(None, '--single-12v-ocp', 0, False), Option(None, '--pump-mode', 1, None), Option(None, '--fan-mode', 1, None), Option(None, '--temperature-sensor', 1, None), Option(None, '--legacy-690lc', 0, False), Option(None, '--non-volatile', 0, False), Option(None, '--direct-access', 0, False), Option(None, '--unsafe', 1, None), Option('-v', '--verbose', 0, False), Option('-g', '--debug', 0, False), Option(None, '--json', 0, False), Option('-d', '--device', 1, None))), Command('set', False), Argument('<channel>', None), Command('screen', False), Argument('<mode>', None), NotRequired(Argument('<value>', None))), Required(Option(None, '--help', 0, False)), Required(Option(None, '--version', 0, False))))
        pattern_options = {Option(None, '--version', 0, False), Option(None, '--help', 0, False)}
        sections   = DocSections(before_usage='liquidctl – monitor and control liquid coolers and other devices.\n\n', usage_header='Usage:', usage_body='\n  liquidctl [options] list\n  liquidctl [options] initialize [all]\n  liquidctl [options] status\n  liquidctl [options] set <channel> speed (<temperature> <percentage>) ...\n  liquidctl [options] set <channel> speed <percentage>\n  liquidctl [options] set <channel> color <mode> [<color>] ...\n  liquidctl [options] set <channel> screen <mode> [<value>]\n  liquidctl --help\n  liquidctl --version\n', after_usage="\nDevice selection options (see: list -v):\n  -m, --match <substring>            Filter devices by description substring\n  -n, --pick <number>                Pick among many results for a given filter\n  --vendor <id>                      Filter devices by hexadecimal vendor ID\n  --product <id>                     Filter devices by hexadecimal product ID\n  --release <number>                 Filter devices by hexadecimal release number\n  --serial <number>                  Filter devices by serial number\n  --bus <bus>                        Filter devices by bus\n  --address <address>                Filter devices by address in bus\n  --usb-port <port>                  Filter devices by USB port in bus\n\nAnimation options (devices/modes can support zero or more):\n  --speed <value>                    Abstract animation speed (device/mode specific)\n  --time-per-color <value>           Time to wait on each color (seconds)\n  --time-off <value>                 Time to wait with the LED turned off (seconds)\n  --alert-threshold <number>         Threshold temperature for a visual alert (°C)\n  --alert-color <color>              Color used by the visual high temperature alert\n  --direction <string>               If the pattern should move forward or backward.\n  --start-led <number>               The first led to start the effect at\n  --maximum-leds <number>            The number of LED's the effect should apply to\n\nOther device options:\n  --single-12v-ocp                   Enable single rail +12V OCP\n  --pump-mode <mode>                 Set the pump mode (certain Corsair coolers)\n  --fan-mode <channel>:<mode>[,...]  Set the mode for each fan (certain Corsair devices)\n  --temperature-sensor <number>      The temperature sensor number for the Commander Pro\n  --legacy-690lc                     Use Asetek 690LC in legacy mode (old Krakens)\n  --non-volatile                     Store on non-volatile controller memory\n  --direct-access                    Directly access the device despite kernel drivers\n  --unsafe <features>                Comma-separated bleeding-edge features to enable\n\nOther interface options:\n  -v, --verbose                      Output additional information\n  -g, --debug                        Show debug information on stderr\n  --json                             JSON output (list/initialization/status)\n  --version                          Display the version number\n  --help                             Show this message\n\nDeprecated:\n  -d, --device <index>           Select device by listing index\n\nCopyright 2018–2023 Jonas Malaco, Marshall Asch, CaseySJ, Tom Frey, Andrew\nRobertson, ParkerMc, Aleksa Savic, Shady Nawara and contributors\n\nSome modules also incorporate or use as reference work by leaty, Ksenija\nStanojevic, Alexander Tong, Jens Neumaier, Kristóf Jakab, Sean Nelson, Chris\nGriffith, notaz, realies and Thomas Pircher. This is mentioned in the module\ndocstring, along with appropriate additional copyright notices.\n\nSPDX-License-Identifier: GPL-3.0-or-later\n\nThis program is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A\nPARTICULAR PURPOSE.  See the GNU General Public License for more details.\n")
        version    = None
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = [], source = ('--bus', 'virtual', 'initialize', '--json'), error = <class 'docopt.DocoptExit'>

    def __init__(
        self,
        source: list[str] | str,
        error: Type[DocoptExit] | Type[DocoptLanguageError] = DocoptExit,
    ) -> None:
        if isinstance(source, list):
            self += source
        else:
>           self += source.split()
E           AttributeError: 'tuple' object has no attribute 'split'

error      = <class 'docopt.DocoptExit'>
self       = []
source     = ('--bus', 'virtual', 'initialize', '--json')

/usr/lib/python3.12/site-packages/docopt/__init__.py:413: AttributeError
______________________________________________________________________________________ test_json_status ______________________________________________________________________________________

main = <function main.<locals>.call_with_args at 0x705288561120>

    def test_json_status(main):
>       code, out, _ = main('test', '--bus', 'virtual', 'status', '--json')

main       = <function main.<locals>.call_with_args at 0x705288561120>

tests/test_cli.py:67: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
tests/test_cli.py:16: in call_with_args
    liquidctl.cli.main()
        args       = ('test', '--bus', 'virtual', 'status', '--json')
        capsys     = <_pytest.capture.CaptureFixture object at 0x7052884e7dd0>
        monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x7052884e7a40>
liquidctl/cli.py:360: in main
    args = docopt(__doc__)
/usr/lib/python3.12/site-packages/docopt/__init__.py:919: in docopt
    parsed_arg_vector = parse_argv(Tokens(argv), list(options), options_first)
        argv       = ('--bus', 'virtual', 'status', '--json')
        default_help = True
        docstring  = ('liquidctl – monitor and control liquid coolers and other devices.\n'
 '\n'
 'Usage:\n'
 '  liquidctl [options] list\n'
 '  liquidctl [options] initialize [all]\n'
 '  liquidctl [options] status\n'
 '  liquidctl [options] set <channel> speed (<temperature> <percentage>) ...\n'
 '  liquidctl [options] set <channel> speed <percentage>\n'
 '  liquidctl [options] set <channel> color <mode> [<color>] ...\n'
 '  liquidctl [options] set <channel> screen <mode> [<value>]\n'
 '  liquidctl --help\n'
 '  liquidctl --version\n'
 '\n'
 'Device selection options (see: list -v):\n'
 '  -m, --match <substring>            Filter devices by description '
 'substring\n'
 '  -n, --pick <number>                Pick among many results for a given '
 'filter\n'
 '  --vendor <id>                      Filter devices by hexadecimal vendor '
 'ID\n'
 '  --product <id>                     Filter devices by hexadecimal product '
 'ID\n'
 '  --release <number>                 Filter devices by hexadecimal release '
 'number\n'
 '  --serial <number>                  Filter devices by serial number\n'
 '  --bus <bus>                        Filter devices by bus\n'
 '  --address <address>                Filter devices by address in bus\n'
 '  --usb-port <port>                  Filter devices by USB port in bus\n'
 '\n'
 'Animation options (devices/modes can support zero or more):\n'
 '  --speed <value>                    Abstract animation speed (device/mode '
 'specific)\n'
 '  --time-per-color <value>           Time to wait on each color (seconds)\n'
 '  --time-off <value>                 Time to wait with the LED turned off '
 '(seconds)\n'
 '  --alert-threshold <number>         Threshold temperature for a visual '
 'alert (°C)\n'
 '  --alert-color <color>              Color used by the visual high '
 'temperature alert\n'
 '  --direction <string>               If the pattern should move forward or '
 'backward.\n'
 '  --start-led <number>               The first led to start the effect at\n'
 "  --maximum-leds <number>            The number of LED's the effect should "
 'apply to\n'
 '\n'
 'Other device options:\n'
 '  --single-12v-ocp                   Enable single rail +12V OCP\n'
 '  --pump-mode <mode>                 Set the pump mode (certain Corsair '
 'coolers)\n'
 '  --fan-mode <channel>:<mode>[,...]  Set the mode for each fan (certain '
 'Corsair devices)\n'
 '  --temperature-sensor <number>      The temperature sensor number for the '
 'Commander Pro\n'
 '  --legacy-690lc                     Use Asetek 690LC in legacy mode (old '
 'Krakens)\n'
 '  --non-volatile                     Store on non-volatile controller '
 'memory\n'
 '  --direct-access                    Directly access the device despite '
 'kernel drivers\n'
 '  --unsafe <features>                Comma-separated bleeding-edge features '
 'to enable\n'
 '\n'
 'Other interface options:\n'
 '  -v, --verbose                      Output additional information\n'
 '  -g, --debug                        Show debug information on stderr\n'
 '  --json                             JSON output '
 '(list/initialization/status)\n'
 '  --version                          Display the version number\n'
 '  --help                             Show this message\n'
 '\n'
 'Deprecated:\n'
 '  -d, --device <index>           Select device by listing index\n'
 '\n'
 'Copyright 2018–2023 Jonas Malaco, Marshall Asch, CaseySJ, Tom Frey, Andrew\n'
 'Robertson, ParkerMc, Aleksa Savic, Shady Nawara and contributors\n'
 '\n'
 'Some modules also incorporate or use as reference work by leaty, Ksenija\n'
 'Stanojevic, Alexander Tong, Jens Neumaier, Kristóf Jakab, Sean Nelson, '
 'Chris\n'
 'Griffith, notaz, realies and Thomas Pircher. This is mentioned in the '
 'module\n'
 'docstring, along with appropriate additional copyright notices.\n'
 '\n'
 'SPDX-License-Identifier: GPL-3.0-or-later\n'
 '\n'
 'This program is distributed in the hope that it will be useful, but WITHOUT '
 'ANY\n'
 'WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS '
 'FOR A\n'
 'PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n')
        options    = [Option('-m', '--match', 1, None),
 Option('-n', '--pick', 1, None),
 Option(None, '--vendor', 1, None),
 Option(None, '--product', 1, None),
 Option(None, '--release', 1, None),
 Option(None, '--serial', 1, None),
 Option(None, '--bus', 1, None),
 Option(None, '--address', 1, None),
 Option(None, '--usb-port', 1, None),
 Option(None, '--speed', 1, None),
 Option(None, '--time-per-color', 1, None),
 Option(None, '--time-off', 1, None),
 Option(None, '--alert-threshold', 1, None),
 Option(None, '--alert-color', 1, None),
 Option(None, '--direction', 1, None),
 Option(None, '--start-led', 1, None),
 Option(None, '--maximum-leds', 1, None),
 Option(None, '--single-12v-ocp', 0, False),
 Option(None, '--pump-mode', 1, None),
 Option(None, '--fan-mode', 1, None),
 Option(None, '--temperature-sensor', 1, None),
 Option(None, '--legacy-690lc', 0, False),
 Option(None, '--non-volatile', 0, False),
 Option(None, '--direct-access', 0, False),
 Option(None, '--unsafe', 1, None),
 Option('-v', '--verbose', 0, False),
 Option('-g', '--debug', 0, False),
 Option(None, '--json', 0, False),
 Option(None, '--version', 0, False),
 Option(None, '--help', 0, False),
 Option('-d', '--device', 1, None)]
        options_first = False
        options_shortcut = OptionsShortcut(Option('-m', '--match', 1, None), Option('-n', '--pick', 1, None), Option(None, '--vendor', 1, None), Option(None, '--product', 1, None), Option(None, '--release', 1, None), Option(None, '--serial', 1, None), Option(None, '--bus', 1, None), Option(None, '--address', 1, None), Option(None, '--usb-port', 1, None), Option(None, '--speed', 1, None), Option(None, '--time-per-color', 1, None), Option(None, '--time-off', 1, None), Option(None, '--alert-threshold', 1, None), Option(None, '--alert-color', 1, None), Option(None, '--direction', 1, None), Option(None, '--start-led', 1, None), Option(None, '--maximum-leds', 1, None), Option(None, '--single-12v-ocp', 0, False), Option(None, '--pump-mode', 1, None), Option(None, '--fan-mode', 1, None), Option(None, '--temperature-sensor', 1, None), Option(None, '--legacy-690lc', 0, False), Option(None, '--non-volatile', 0, False), Option(None, '--direct-access', 0, False), Option(None, '--unsafe', 1, None), Option('-v', '--verbose', 0, False), Option('-g', '--debug', 0, False), Option(None, '--json', 0, False), Option('-d', '--device', 1, None))
        pattern    = Required(Either(Required(NotRequired(OptionsShortcut(Option('-m', '--match', 1, None), Option('-n', '--pick', 1, None), Option(None, '--vendor', 1, None), Option(None, '--product', 1, None), Option(None, '--release', 1, None), Option(None, '--serial', 1, None), Option(None, '--bus', 1, None), Option(None, '--address', 1, None), Option(None, '--usb-port', 1, None), Option(None, '--speed', 1, None), Option(None, '--time-per-color', 1, None), Option(None, '--time-off', 1, None), Option(None, '--alert-threshold', 1, None), Option(None, '--alert-color', 1, None), Option(None, '--direction', 1, None), Option(None, '--start-led', 1, None), Option(None, '--maximum-leds', 1, None), Option(None, '--single-12v-ocp', 0, False), Option(None, '--pump-mode', 1, None), Option(None, '--fan-mode', 1, None), Option(None, '--temperature-sensor', 1, None), Option(None, '--legacy-690lc', 0, False), Option(None, '--non-volatile', 0, False), Option(None, '--direct-access', 0, False), Option(None, '--unsafe', 1, None), Option('-v', '--verbose', 0, False), Option('-g', '--debug', 0, False), Option(None, '--json', 0, False), Option('-d', '--device', 1, None))), Command('list', False)), Required(NotRequired(OptionsShortcut(Option('-m', '--match', 1, None), Option('-n', '--pick', 1, None), Option(None, '--vendor', 1, None), Option(None, '--product', 1, None), Option(None, '--release', 1, None), Option(None, '--serial', 1, None), Option(None, '--bus', 1, None), Option(None, '--address', 1, None), Option(None, '--usb-port', 1, None), Option(None, '--speed', 1, None), Option(None, '--time-per-color', 1, None), Option(None, '--time-off', 1, None), Option(None, '--alert-threshold', 1, None), Option(None, '--alert-color', 1, None), Option(None, '--direction', 1, None), Option(None, '--start-led', 1, None), Option(None, '--maximum-leds', 1, None), Option(None, '--single-12v-ocp', 0, False), Option(None, '--pump-mode', 1, None), Option(None, '--fan-mode', 1, None), Option(None, '--temperature-sensor', 1, None), Option(None, '--legacy-690lc', 0, False), Option(None, '--non-volatile', 0, False), Option(None, '--direct-access', 0, False), Option(None, '--unsafe', 1, None), Option('-v', '--verbose', 0, False), Option('-g', '--debug', 0, False), Option(None, '--json', 0, False), Option('-d', '--device', 1, None))), Command('initialize', False), NotRequired(Command('all', False))), Required(NotRequired(OptionsShortcut(Option('-m', '--match', 1, None), Option('-n', '--pick', 1, None), Option(None, '--vendor', 1, None), Option(None, '--product', 1, None), Option(None, '--release', 1, None), Option(None, '--serial', 1, None), Option(None, '--bus', 1, None), Option(None, '--address', 1, None), Option(None, '--usb-port', 1, None), Option(None, '--speed', 1, None), Option(None, '--time-per-color', 1, None), Option(None, '--time-off', 1, None), Option(None, '--alert-threshold', 1, None), Option(None, '--alert-color', 1, None), Option(None, '--direction', 1, None), Option(None, '--start-led', 1, None), Option(None, '--maximum-leds', 1, None), Option(None, '--single-12v-ocp', 0, False), Option(None, '--pump-mode', 1, None), Option(None, '--fan-mode', 1, None), Option(None, '--temperature-sensor', 1, None), Option(None, '--legacy-690lc', 0, False), Option(None, '--non-volatile', 0, False), Option(None, '--direct-access', 0, False), Option(None, '--unsafe', 1, None), Option('-v', '--verbose', 0, False), Option('-g', '--debug', 0, False), Option(None, '--json', 0, False), Option('-d', '--device', 1, None))), Command('status', False)), Required(NotRequired(OptionsShortcut(Option('-m', '--match', 1, None), Option('-n', '--pick', 1, None), Option(None, '--vendor', 1, None), Option(None, '--product', 1, None), Option(None, '--release', 1, None), Option(None, '--serial', 1, None), Option(None, '--bus', 1, None), Option(None, '--address', 1, None), Option(None, '--usb-port', 1, None), Option(None, '--speed', 1, None), Option(None, '--time-per-color', 1, None), Option(None, '--time-off', 1, None), Option(None, '--alert-threshold', 1, None), Option(None, '--alert-color', 1, None), Option(None, '--direction', 1, None), Option(None, '--start-led', 1, None), Option(None, '--maximum-leds', 1, None), Option(None, '--single-12v-ocp', 0, False), Option(None, '--pump-mode', 1, None), Option(None, '--fan-mode', 1, None), Option(None, '--temperature-sensor', 1, None), Option(None, '--legacy-690lc', 0, False), Option(None, '--non-volatile', 0, False), Option(None, '--direct-access', 0, False), Option(None, '--unsafe', 1, None), Option('-v', '--verbose', 0, False), Option('-g', '--debug', 0, False), Option(None, '--json', 0, False), Option('-d', '--device', 1, None))), Command('set', False), Argument('<channel>', None), Command('speed', False), OneOrMore(Required(Argument('<temperature>', None), Argument('<percentage>', None)))), Required(NotRequired(OptionsShortcut(Option('-m', '--match', 1, None), Option('-n', '--pick', 1, None), Option(None, '--vendor', 1, None), Option(None, '--product', 1, None), Option(None, '--release', 1, None), Option(None, '--serial', 1, None), Option(None, '--bus', 1, None), Option(None, '--address', 1, None), Option(None, '--usb-port', 1, None), Option(None, '--speed', 1, None), Option(None, '--time-per-color', 1, None), Option(None, '--time-off', 1, None), Option(None, '--alert-threshold', 1, None), Option(None, '--alert-color', 1, None), Option(None, '--direction', 1, None), Option(None, '--start-led', 1, None), Option(None, '--maximum-leds', 1, None), Option(None, '--single-12v-ocp', 0, False), Option(None, '--pump-mode', 1, None), Option(None, '--fan-mode', 1, None), Option(None, '--temperature-sensor', 1, None), Option(None, '--legacy-690lc', 0, False), Option(None, '--non-volatile', 0, False), Option(None, '--direct-access', 0, False), Option(None, '--unsafe', 1, None), Option('-v', '--verbose', 0, False), Option('-g', '--debug', 0, False), Option(None, '--json', 0, False), Option('-d', '--device', 1, None))), Command('set', False), Argument('<channel>', None), Command('speed', False), Argument('<percentage>', None)), Required(NotRequired(OptionsShortcut(Option('-m', '--match', 1, None), Option('-n', '--pick', 1, None), Option(None, '--vendor', 1, None), Option(None, '--product', 1, None), Option(None, '--release', 1, None), Option(None, '--serial', 1, None), Option(None, '--bus', 1, None), Option(None, '--address', 1, None), Option(None, '--usb-port', 1, None), Option(None, '--speed', 1, None), Option(None, '--time-per-color', 1, None), Option(None, '--time-off', 1, None), Option(None, '--alert-threshold', 1, None), Option(None, '--alert-color', 1, None), Option(None, '--direction', 1, None), Option(None, '--start-led', 1, None), Option(None, '--maximum-leds', 1, None), Option(None, '--single-12v-ocp', 0, False), Option(None, '--pump-mode', 1, None), Option(None, '--fan-mode', 1, None), Option(None, '--temperature-sensor', 1, None), Option(None, '--legacy-690lc', 0, False), Option(None, '--non-volatile', 0, False), Option(None, '--direct-access', 0, False), Option(None, '--unsafe', 1, None), Option('-v', '--verbose', 0, False), Option('-g', '--debug', 0, False), Option(None, '--json', 0, False), Option('-d', '--device', 1, None))), Command('set', False), Argument('<channel>', None), Command('color', False), Argument('<mode>', None), OneOrMore(NotRequired(Argument('<color>', None)))), Required(NotRequired(OptionsShortcut(Option('-m', '--match', 1, None), Option('-n', '--pick', 1, None), Option(None, '--vendor', 1, None), Option(None, '--product', 1, None), Option(None, '--release', 1, None), Option(None, '--serial', 1, None), Option(None, '--bus', 1, None), Option(None, '--address', 1, None), Option(None, '--usb-port', 1, None), Option(None, '--speed', 1, None), Option(None, '--time-per-color', 1, None), Option(None, '--time-off', 1, None), Option(None, '--alert-threshold', 1, None), Option(None, '--alert-color', 1, None), Option(None, '--direction', 1, None), Option(None, '--start-led', 1, None), Option(None, '--maximum-leds', 1, None), Option(None, '--single-12v-ocp', 0, False), Option(None, '--pump-mode', 1, None), Option(None, '--fan-mode', 1, None), Option(None, '--temperature-sensor', 1, None), Option(None, '--legacy-690lc', 0, False), Option(None, '--non-volatile', 0, False), Option(None, '--direct-access', 0, False), Option(None, '--unsafe', 1, None), Option('-v', '--verbose', 0, False), Option('-g', '--debug', 0, False), Option(None, '--json', 0, False), Option('-d', '--device', 1, None))), Command('set', False), Argument('<channel>', None), Command('screen', False), Argument('<mode>', None), NotRequired(Argument('<value>', None))), Required(Option(None, '--help', 0, False)), Required(Option(None, '--version', 0, False))))
        pattern_options = {Option(None, '--version', 0, False), Option(None, '--help', 0, False)}
        sections   = DocSections(before_usage='liquidctl – monitor and control liquid coolers and other devices.\n\n', usage_header='Usage:', usage_body='\n  liquidctl [options] list\n  liquidctl [options] initialize [all]\n  liquidctl [options] status\n  liquidctl [options] set <channel> speed (<temperature> <percentage>) ...\n  liquidctl [options] set <channel> speed <percentage>\n  liquidctl [options] set <channel> color <mode> [<color>] ...\n  liquidctl [options] set <channel> screen <mode> [<value>]\n  liquidctl --help\n  liquidctl --version\n', after_usage="\nDevice selection options (see: list -v):\n  -m, --match <substring>            Filter devices by description substring\n  -n, --pick <number>                Pick among many results for a given filter\n  --vendor <id>                      Filter devices by hexadecimal vendor ID\n  --product <id>                     Filter devices by hexadecimal product ID\n  --release <number>                 Filter devices by hexadecimal release number\n  --serial <number>                  Filter devices by serial number\n  --bus <bus>                        Filter devices by bus\n  --address <address>                Filter devices by address in bus\n  --usb-port <port>                  Filter devices by USB port in bus\n\nAnimation options (devices/modes can support zero or more):\n  --speed <value>                    Abstract animation speed (device/mode specific)\n  --time-per-color <value>           Time to wait on each color (seconds)\n  --time-off <value>                 Time to wait with the LED turned off (seconds)\n  --alert-threshold <number>         Threshold temperature for a visual alert (°C)\n  --alert-color <color>              Color used by the visual high temperature alert\n  --direction <string>               If the pattern should move forward or backward.\n  --start-led <number>               The first led to start the effect at\n  --maximum-leds <number>            The number of LED's the effect should apply to\n\nOther device options:\n  --single-12v-ocp                   Enable single rail +12V OCP\n  --pump-mode <mode>                 Set the pump mode (certain Corsair coolers)\n  --fan-mode <channel>:<mode>[,...]  Set the mode for each fan (certain Corsair devices)\n  --temperature-sensor <number>      The temperature sensor number for the Commander Pro\n  --legacy-690lc                     Use Asetek 690LC in legacy mode (old Krakens)\n  --non-volatile                     Store on non-volatile controller memory\n  --direct-access                    Directly access the device despite kernel drivers\n  --unsafe <features>                Comma-separated bleeding-edge features to enable\n\nOther interface options:\n  -v, --verbose                      Output additional information\n  -g, --debug                        Show debug information on stderr\n  --json                             JSON output (list/initialization/status)\n  --version                          Display the version number\n  --help                             Show this message\n\nDeprecated:\n  -d, --device <index>           Select device by listing index\n\nCopyright 2018–2023 Jonas Malaco, Marshall Asch, CaseySJ, Tom Frey, Andrew\nRobertson, ParkerMc, Aleksa Savic, Shady Nawara and contributors\n\nSome modules also incorporate or use as reference work by leaty, Ksenija\nStanojevic, Alexander Tong, Jens Neumaier, Kristóf Jakab, Sean Nelson, Chris\nGriffith, notaz, realies and Thomas Pircher. This is mentioned in the module\ndocstring, along with appropriate additional copyright notices.\n\nSPDX-License-Identifier: GPL-3.0-or-later\n\nThis program is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A\nPARTICULAR PURPOSE.  See the GNU General Public License for more details.\n")
        version    = None
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = [], source = ('--bus', 'virtual', 'status', '--json'), error = <class 'docopt.DocoptExit'>

    def __init__(
        self,
        source: list[str] | str,
        error: Type[DocoptExit] | Type[DocoptLanguageError] = DocoptExit,
    ) -> None:
        if isinstance(source, list):
            self += source
        else:
>           self += source.split()
E           AttributeError: 'tuple' object has no attribute 'split'

error      = <class 'docopt.DocoptExit'>
self       = []
source     = ('--bus', 'virtual', 'status', '--json')

/usr/lib/python3.12/site-packages/docopt/__init__.py:413: AttributeError

Affected device

test_cli.py

Does your version of liquidctl support the device in question?

Yes, my version supports it

Operating system and version

Gentoo Linux

Installation method

Gentoo package manger

Version of liquidctl

v1.13.0

@ZeroChaos- ZeroChaos- added the bug Apparent bug in liquidctl label May 21, 2024
@ZeroChaos-
Copy link
Author

Full build and test log is available here if it helps https://pentoo.org/~zero/app-misc:liquidctl-1.13.0:20240521-173117.log

@jonasmalacofilho
Copy link
Member

You seem to be using docopt-ng...

While I can't tell for sure (the build logs don't even mention the use of docopt-ng, much less a specific version), the issue is probably caused by the monkeypatching or argv we do for the tests, which changes its type from list to tuple.

I'll post a patch for you to try in a bit.

jonasmalacofilho added a commit that referenced this issue May 21, 2024
When setting up for the CLI tests, we inadvertently change the type of
sys.argv from list to tuple. That worked with OG docopt, but breaks
docopt-ng. More importantly, the Python docs say sys.argv is a _list_.

So even though docopt was able to handle it being a tuple, and docopt-ng
seems (from a cursory look at its source) to still handle it being a
string, let's use the correct type.

Fixes: #708
@jonasmalacofilho
Copy link
Member

Please give #709 a test, and let me know if it fixes this issue.

@ZeroChaos-
Copy link
Author

Awesome, thanks for the quick work. Yes, this does fix the issue with the tests failing. All tests now pass except for the known bug here #661

@jonasmalacofilho
Copy link
Member

Thanks!

jonasmalacofilho added a commit that referenced this issue May 22, 2024
When setting up for the CLI tests, we inadvertently change the type of
sys.argv from list to tuple. That worked with OG docopt, but breaks
docopt-ng. More importantly, the Python docs say sys.argv is a _list_.

So even though docopt was able to handle it being a tuple, and docopt-ng
seems (from a cursory look at its source) to still handle it being a
string, let's use the correct type.

Fixes: #708
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Apparent bug in liquidctl
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants