falyx 0.1.55__py3-none-any.whl → 0.1.57__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- falyx/__init__.py +1 -0
- falyx/action/__init__.py +4 -0
- falyx/action/action_group.py +6 -0
- falyx/action/base_action.py +2 -1
- falyx/action/chained_action.py +7 -1
- falyx/action/confirm_action.py +217 -0
- falyx/action/load_file_action.py +7 -9
- falyx/action/menu_action.py +0 -7
- falyx/action/prompt_menu_action.py +0 -6
- falyx/action/save_file_action.py +199 -11
- falyx/action/select_file_action.py +5 -8
- falyx/action/selection_action.py +0 -8
- falyx/action/user_input_action.py +0 -7
- falyx/bottom_bar.py +2 -2
- falyx/command.py +8 -4
- falyx/completer.py +47 -0
- falyx/config.py +1 -3
- falyx/console.py +5 -0
- falyx/context.py +3 -1
- falyx/execution_registry.py +1 -0
- falyx/falyx.py +8 -16
- falyx/falyx_completer.py +105 -30
- falyx/init.py +1 -3
- falyx/parser/argument.py +1 -0
- falyx/parser/command_argument_parser.py +107 -33
- falyx/parser/utils.py +3 -2
- falyx/selection.py +1 -16
- falyx/validators.py +24 -0
- falyx/version.py +1 -1
- {falyx-0.1.55.dist-info → falyx-0.1.57.dist-info}/METADATA +1 -1
- {falyx-0.1.55.dist-info → falyx-0.1.57.dist-info}/RECORD +34 -31
- {falyx-0.1.55.dist-info → falyx-0.1.57.dist-info}/LICENSE +0 -0
- {falyx-0.1.55.dist-info → falyx-0.1.57.dist-info}/WHEEL +0 -0
- {falyx-0.1.55.dist-info → falyx-0.1.57.dist-info}/entry_points.txt +0 -0
@@ -7,9 +7,9 @@ from typing import Any, Iterable
|
|
7
7
|
|
8
8
|
from rich.console import Console
|
9
9
|
from rich.markup import escape
|
10
|
-
from rich.text import Text
|
11
10
|
|
12
11
|
from falyx.action.base_action import BaseAction
|
12
|
+
from falyx.console import console
|
13
13
|
from falyx.exceptions import CommandArgumentError
|
14
14
|
from falyx.parser.argument import Argument
|
15
15
|
from falyx.parser.argument_action import ArgumentAction
|
@@ -47,7 +47,7 @@ class CommandArgumentParser:
|
|
47
47
|
aliases: list[str] | None = None,
|
48
48
|
) -> None:
|
49
49
|
"""Initialize the CommandArgumentParser."""
|
50
|
-
self.console =
|
50
|
+
self.console: Console = console
|
51
51
|
self.command_key: str = command_key
|
52
52
|
self.command_description: str = command_description
|
53
53
|
self.command_style: str = command_style
|
@@ -301,6 +301,7 @@ class CommandArgumentParser:
|
|
301
301
|
help: str = "",
|
302
302
|
dest: str | None = None,
|
303
303
|
resolver: BaseAction | None = None,
|
304
|
+
lazy_resolver: bool = False,
|
304
305
|
) -> None:
|
305
306
|
"""Add an argument to the parser.
|
306
307
|
For `ArgumentAction.ACTION`, `nargs` and `type` determine how many and what kind
|
@@ -349,6 +350,10 @@ class CommandArgumentParser:
|
|
349
350
|
f"Default value '{default}' not in allowed choices: {choices}"
|
350
351
|
)
|
351
352
|
required = self._determine_required(required, positional, nargs)
|
353
|
+
if not isinstance(lazy_resolver, bool):
|
354
|
+
raise CommandArgumentError(
|
355
|
+
f"lazy_resolver must be a boolean, got {type(lazy_resolver)}"
|
356
|
+
)
|
352
357
|
argument = Argument(
|
353
358
|
flags=flags,
|
354
359
|
dest=dest,
|
@@ -361,6 +366,7 @@ class CommandArgumentParser:
|
|
361
366
|
nargs=nargs,
|
362
367
|
positional=positional,
|
363
368
|
resolver=resolver,
|
369
|
+
lazy_resolver=lazy_resolver,
|
364
370
|
)
|
365
371
|
for flag in flags:
|
366
372
|
if flag in self._flag_map:
|
@@ -446,6 +452,7 @@ class CommandArgumentParser:
|
|
446
452
|
result: dict[str, Any],
|
447
453
|
positional_args: list[Argument],
|
448
454
|
consumed_positional_indicies: set[int],
|
455
|
+
from_validate: bool = False,
|
449
456
|
) -> int:
|
450
457
|
remaining_positional_args = [
|
451
458
|
(j, spec)
|
@@ -466,6 +473,10 @@ class CommandArgumentParser:
|
|
466
473
|
or isinstance(next_spec.nargs, str)
|
467
474
|
and next_spec.nargs in ("+", "*", "?")
|
468
475
|
), f"Invalid nargs value: {spec.nargs}"
|
476
|
+
|
477
|
+
if next_spec.default:
|
478
|
+
continue
|
479
|
+
|
469
480
|
if next_spec.nargs is None:
|
470
481
|
min_required += 1
|
471
482
|
elif isinstance(next_spec.nargs, int):
|
@@ -473,9 +484,9 @@ class CommandArgumentParser:
|
|
473
484
|
elif next_spec.nargs == "+":
|
474
485
|
min_required += 1
|
475
486
|
elif next_spec.nargs == "?":
|
476
|
-
|
487
|
+
continue
|
477
488
|
elif next_spec.nargs == "*":
|
478
|
-
|
489
|
+
continue
|
479
490
|
|
480
491
|
slice_args = args[i:] if is_last else args[i : i + (remaining - min_required)]
|
481
492
|
values, new_i = self._consume_nargs(slice_args, 0, spec)
|
@@ -484,19 +495,36 @@ class CommandArgumentParser:
|
|
484
495
|
try:
|
485
496
|
typed = [coerce_value(value, spec.type) for value in values]
|
486
497
|
except Exception as error:
|
487
|
-
|
488
|
-
|
489
|
-
|
498
|
+
if len(args[i - new_i :]) == 1 and args[i - new_i].startswith("-"):
|
499
|
+
token = args[i - new_i]
|
500
|
+
valid_flags = [
|
501
|
+
flag for flag in self._flag_map if flag.startswith(token)
|
502
|
+
]
|
503
|
+
if valid_flags:
|
504
|
+
raise CommandArgumentError(
|
505
|
+
f"Unrecognized option '{token}'. Did you mean one of: {', '.join(valid_flags)}?"
|
506
|
+
) from error
|
507
|
+
else:
|
508
|
+
raise CommandArgumentError(
|
509
|
+
f"Unrecognized option '{token}'. Use --help to see available options."
|
510
|
+
) from error
|
511
|
+
else:
|
512
|
+
raise CommandArgumentError(
|
513
|
+
f"Invalid value for '{spec.dest}': {error}"
|
514
|
+
) from error
|
490
515
|
if spec.action == ArgumentAction.ACTION:
|
491
516
|
assert isinstance(
|
492
517
|
spec.resolver, BaseAction
|
493
518
|
), "resolver should be an instance of BaseAction"
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
519
|
+
if not spec.lazy_resolver or not from_validate:
|
520
|
+
try:
|
521
|
+
result[spec.dest] = await spec.resolver(*typed)
|
522
|
+
except Exception as error:
|
523
|
+
raise CommandArgumentError(
|
524
|
+
f"[{spec.dest}] Action failed: {error}"
|
525
|
+
) from error
|
526
|
+
elif not typed and spec.default:
|
527
|
+
result[spec.dest] = spec.default
|
500
528
|
elif spec.action == ArgumentAction.APPEND:
|
501
529
|
assert result.get(spec.dest) is not None, "dest should not be None"
|
502
530
|
if spec.nargs is None:
|
@@ -515,10 +543,22 @@ class CommandArgumentParser:
|
|
515
543
|
consumed_positional_indicies.add(j)
|
516
544
|
|
517
545
|
if i < len(args):
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
546
|
+
if len(args[i:]) == 1 and args[i].startswith("-"):
|
547
|
+
token = args[i]
|
548
|
+
valid_flags = [flag for flag in self._flag_map if flag.startswith(token)]
|
549
|
+
if valid_flags:
|
550
|
+
raise CommandArgumentError(
|
551
|
+
f"Unrecognized option '{token}'. Did you mean one of: {', '.join(valid_flags)}?"
|
552
|
+
)
|
553
|
+
else:
|
554
|
+
raise CommandArgumentError(
|
555
|
+
f"Unrecognized option '{token}'. Use --help to see available options."
|
556
|
+
)
|
557
|
+
else:
|
558
|
+
plural = "s" if len(args[i:]) > 1 else ""
|
559
|
+
raise CommandArgumentError(
|
560
|
+
f"Unexpected positional argument{plural}: {', '.join(args[i:])}"
|
561
|
+
)
|
522
562
|
|
523
563
|
return i
|
524
564
|
|
@@ -624,9 +664,27 @@ class CommandArgumentParser:
|
|
624
664
|
f"Invalid value for '{spec.dest}': {error}"
|
625
665
|
) from error
|
626
666
|
if not typed_values and spec.nargs not in ("*", "?"):
|
627
|
-
|
628
|
-
|
629
|
-
|
667
|
+
choices = []
|
668
|
+
if spec.default:
|
669
|
+
choices.append(f"default={spec.default}")
|
670
|
+
if spec.choices:
|
671
|
+
choices.append(f"choices={spec.choices}")
|
672
|
+
if choices:
|
673
|
+
choices_text = ", ".join(choices)
|
674
|
+
raise CommandArgumentError(
|
675
|
+
f"Argument '{spec.dest}' requires a value. {choices_text}"
|
676
|
+
)
|
677
|
+
elif spec.nargs is None:
|
678
|
+
try:
|
679
|
+
raise CommandArgumentError(
|
680
|
+
f"Enter a {spec.type.__name__} value for '{spec.dest}'"
|
681
|
+
)
|
682
|
+
except AttributeError:
|
683
|
+
raise CommandArgumentError(f"Enter a value for '{spec.dest}'")
|
684
|
+
else:
|
685
|
+
raise CommandArgumentError(
|
686
|
+
f"Argument '{spec.dest}' requires a value. Expected {spec.nargs} values."
|
687
|
+
)
|
630
688
|
if spec.nargs in (None, 1, "?") and spec.action != ArgumentAction.APPEND:
|
631
689
|
result[spec.dest] = (
|
632
690
|
typed_values[0] if len(typed_values) == 1 else typed_values
|
@@ -637,7 +695,15 @@ class CommandArgumentParser:
|
|
637
695
|
i = new_i
|
638
696
|
elif token.startswith("-"):
|
639
697
|
# Handle unrecognized option
|
640
|
-
|
698
|
+
valid_flags = [flag for flag in self._flag_map if flag.startswith(token)]
|
699
|
+
if valid_flags:
|
700
|
+
raise CommandArgumentError(
|
701
|
+
f"Unrecognized option '{token}'. Did you mean one of: {', '.join(valid_flags)}?"
|
702
|
+
)
|
703
|
+
else:
|
704
|
+
raise CommandArgumentError(
|
705
|
+
f"Unrecognized option '{token}'. Use --help to see available options."
|
706
|
+
)
|
641
707
|
else:
|
642
708
|
# Get the next flagged argument index if it exists
|
643
709
|
next_flagged_index = -1
|
@@ -652,6 +718,7 @@ class CommandArgumentParser:
|
|
652
718
|
result,
|
653
719
|
positional_args,
|
654
720
|
consumed_positional_indices,
|
721
|
+
from_validate=from_validate,
|
655
722
|
)
|
656
723
|
i += args_consumed
|
657
724
|
return i
|
@@ -692,11 +759,20 @@ class CommandArgumentParser:
|
|
692
759
|
if spec.dest == "help":
|
693
760
|
continue
|
694
761
|
if spec.required and not result.get(spec.dest):
|
695
|
-
|
762
|
+
help_text = f" help: {spec.help}" if spec.help else ""
|
763
|
+
if (
|
764
|
+
spec.action == ArgumentAction.ACTION
|
765
|
+
and spec.lazy_resolver
|
766
|
+
and from_validate
|
767
|
+
):
|
768
|
+
continue # Lazy resolvers are not validated here
|
769
|
+
raise CommandArgumentError(
|
770
|
+
f"Missing required argument '{spec.dest}': {spec.get_choice_text()}{help_text}"
|
771
|
+
)
|
696
772
|
|
697
773
|
if spec.choices and result.get(spec.dest) not in spec.choices:
|
698
774
|
raise CommandArgumentError(
|
699
|
-
f"Invalid value for {spec.dest}: must be one of {spec.choices}"
|
775
|
+
f"Invalid value for '{spec.dest}': must be one of {{{', '.join(spec.choices)}}}"
|
700
776
|
)
|
701
777
|
|
702
778
|
if spec.action == ArgumentAction.ACTION:
|
@@ -705,23 +781,23 @@ class CommandArgumentParser:
|
|
705
781
|
if isinstance(spec.nargs, int) and spec.nargs > 1:
|
706
782
|
assert isinstance(
|
707
783
|
result.get(spec.dest), list
|
708
|
-
), f"Invalid value for {spec.dest}: expected a list"
|
784
|
+
), f"Invalid value for '{spec.dest}': expected a list"
|
709
785
|
if not result[spec.dest] and not spec.required:
|
710
786
|
continue
|
711
787
|
if spec.action == ArgumentAction.APPEND:
|
712
788
|
for group in result[spec.dest]:
|
713
789
|
if len(group) % spec.nargs != 0:
|
714
790
|
raise CommandArgumentError(
|
715
|
-
f"Invalid number of values for {spec.dest}: expected a multiple of {spec.nargs}"
|
791
|
+
f"Invalid number of values for '{spec.dest}': expected a multiple of {spec.nargs}"
|
716
792
|
)
|
717
793
|
elif spec.action == ArgumentAction.EXTEND:
|
718
794
|
if len(result[spec.dest]) % spec.nargs != 0:
|
719
795
|
raise CommandArgumentError(
|
720
|
-
f"Invalid number of values for {spec.dest}: expected a multiple of {spec.nargs}"
|
796
|
+
f"Invalid number of values for '{spec.dest}': expected a multiple of {spec.nargs}"
|
721
797
|
)
|
722
798
|
elif len(result[spec.dest]) != spec.nargs:
|
723
799
|
raise CommandArgumentError(
|
724
|
-
f"Invalid number of values for {spec.dest}: expected {spec.nargs}, got {len(result[spec.dest])}"
|
800
|
+
f"Invalid number of values for '{spec.dest}': expected {spec.nargs}, got {len(result[spec.dest])}"
|
725
801
|
)
|
726
802
|
|
727
803
|
result.pop("help", None)
|
@@ -807,22 +883,20 @@ class CommandArgumentParser:
|
|
807
883
|
self.console.print("[bold]positional:[/bold]")
|
808
884
|
for arg in self._positional.values():
|
809
885
|
flags = arg.get_positional_text()
|
810
|
-
arg_line =
|
886
|
+
arg_line = f" {flags:<30} "
|
811
887
|
help_text = arg.help or ""
|
812
888
|
if help_text and len(flags) > 30:
|
813
889
|
help_text = f"\n{'':<33}{help_text}"
|
814
|
-
|
815
|
-
self.console.print(arg_line)
|
890
|
+
self.console.print(f"{arg_line}{help_text}")
|
816
891
|
self.console.print("[bold]options:[/bold]")
|
817
892
|
for arg in self._keyword_list:
|
818
893
|
flags = ", ".join(arg.flags)
|
819
894
|
flags_choice = f"{flags} {arg.get_choice_text()}"
|
820
|
-
arg_line =
|
895
|
+
arg_line = f" {flags_choice:<30} "
|
821
896
|
help_text = arg.help or ""
|
822
897
|
if help_text and len(flags_choice) > 30:
|
823
898
|
help_text = f"\n{'':<33}{help_text}"
|
824
|
-
|
825
|
-
self.console.print(arg_line)
|
899
|
+
self.console.print(f"{arg_line}{help_text}")
|
826
900
|
|
827
901
|
# Epilog
|
828
902
|
if self.help_epilog:
|
falyx/parser/utils.py
CHANGED
@@ -37,7 +37,8 @@ def coerce_enum(value: Any, enum_type: EnumMeta) -> Any:
|
|
37
37
|
coerced_value = base_type(value)
|
38
38
|
return enum_type(coerced_value)
|
39
39
|
except (ValueError, TypeError):
|
40
|
-
|
40
|
+
values = [str(enum.value) for enum in enum_type]
|
41
|
+
raise ValueError(f"'{value}' should be one of {{{', '.join(values)}}}") from None
|
41
42
|
|
42
43
|
|
43
44
|
def coerce_value(value: str, target_type: type) -> Any:
|
@@ -57,7 +58,7 @@ def coerce_value(value: str, target_type: type) -> Any:
|
|
57
58
|
return coerce_value(value, arg)
|
58
59
|
except Exception:
|
59
60
|
continue
|
60
|
-
raise ValueError(f"Value '{value}' could not be coerced to any of {args
|
61
|
+
raise ValueError(f"Value '{value}' could not be coerced to any of {args}")
|
61
62
|
|
62
63
|
if isinstance(target_type, EnumMeta):
|
63
64
|
return coerce_enum(value, target_type)
|
falyx/selection.py
CHANGED
@@ -5,10 +5,10 @@ from typing import Any, Callable, KeysView, Sequence
|
|
5
5
|
|
6
6
|
from prompt_toolkit import PromptSession
|
7
7
|
from rich import box
|
8
|
-
from rich.console import Console
|
9
8
|
from rich.markup import escape
|
10
9
|
from rich.table import Table
|
11
10
|
|
11
|
+
from falyx.console import console
|
12
12
|
from falyx.themes import OneColors
|
13
13
|
from falyx.utils import CaseInsensitiveDict, chunks
|
14
14
|
from falyx.validators import MultiIndexValidator, MultiKeyValidator
|
@@ -267,7 +267,6 @@ async def prompt_for_index(
|
|
267
267
|
*,
|
268
268
|
min_index: int = 0,
|
269
269
|
default_selection: str = "",
|
270
|
-
console: Console | None = None,
|
271
270
|
prompt_session: PromptSession | None = None,
|
272
271
|
prompt_message: str = "Select an option > ",
|
273
272
|
show_table: bool = True,
|
@@ -277,7 +276,6 @@ async def prompt_for_index(
|
|
277
276
|
cancel_key: str = "",
|
278
277
|
) -> int | list[int]:
|
279
278
|
prompt_session = prompt_session or PromptSession()
|
280
|
-
console = console or Console(color_system="truecolor")
|
281
279
|
|
282
280
|
if show_table:
|
283
281
|
console.print(table, justify="center")
|
@@ -307,7 +305,6 @@ async def prompt_for_selection(
|
|
307
305
|
table: Table,
|
308
306
|
*,
|
309
307
|
default_selection: str = "",
|
310
|
-
console: Console | None = None,
|
311
308
|
prompt_session: PromptSession | None = None,
|
312
309
|
prompt_message: str = "Select an option > ",
|
313
310
|
show_table: bool = True,
|
@@ -318,7 +315,6 @@ async def prompt_for_selection(
|
|
318
315
|
) -> str | list[str]:
|
319
316
|
"""Prompt the user to select a key from a set of options. Return the selected key."""
|
320
317
|
prompt_session = prompt_session or PromptSession()
|
321
|
-
console = console or Console(color_system="truecolor")
|
322
318
|
|
323
319
|
if show_table:
|
324
320
|
console.print(table, justify="center")
|
@@ -342,7 +338,6 @@ async def select_value_from_list(
|
|
342
338
|
title: str,
|
343
339
|
selections: Sequence[str],
|
344
340
|
*,
|
345
|
-
console: Console | None = None,
|
346
341
|
prompt_session: PromptSession | None = None,
|
347
342
|
prompt_message: str = "Select an option > ",
|
348
343
|
default_selection: str = "",
|
@@ -381,13 +376,11 @@ async def select_value_from_list(
|
|
381
376
|
highlight=highlight,
|
382
377
|
)
|
383
378
|
prompt_session = prompt_session or PromptSession()
|
384
|
-
console = console or Console(color_system="truecolor")
|
385
379
|
|
386
380
|
selection_index = await prompt_for_index(
|
387
381
|
len(selections) - 1,
|
388
382
|
table,
|
389
383
|
default_selection=default_selection,
|
390
|
-
console=console,
|
391
384
|
prompt_session=prompt_session,
|
392
385
|
prompt_message=prompt_message,
|
393
386
|
number_selections=number_selections,
|
@@ -405,7 +398,6 @@ async def select_key_from_dict(
|
|
405
398
|
selections: dict[str, SelectionOption],
|
406
399
|
table: Table,
|
407
400
|
*,
|
408
|
-
console: Console | None = None,
|
409
401
|
prompt_session: PromptSession | None = None,
|
410
402
|
prompt_message: str = "Select an option > ",
|
411
403
|
default_selection: str = "",
|
@@ -416,7 +408,6 @@ async def select_key_from_dict(
|
|
416
408
|
) -> str | list[str]:
|
417
409
|
"""Prompt for a key from a dict, returns the key."""
|
418
410
|
prompt_session = prompt_session or PromptSession()
|
419
|
-
console = console or Console(color_system="truecolor")
|
420
411
|
|
421
412
|
console.print(table, justify="center")
|
422
413
|
|
@@ -424,7 +415,6 @@ async def select_key_from_dict(
|
|
424
415
|
selections.keys(),
|
425
416
|
table,
|
426
417
|
default_selection=default_selection,
|
427
|
-
console=console,
|
428
418
|
prompt_session=prompt_session,
|
429
419
|
prompt_message=prompt_message,
|
430
420
|
number_selections=number_selections,
|
@@ -438,7 +428,6 @@ async def select_value_from_dict(
|
|
438
428
|
selections: dict[str, SelectionOption],
|
439
429
|
table: Table,
|
440
430
|
*,
|
441
|
-
console: Console | None = None,
|
442
431
|
prompt_session: PromptSession | None = None,
|
443
432
|
prompt_message: str = "Select an option > ",
|
444
433
|
default_selection: str = "",
|
@@ -449,7 +438,6 @@ async def select_value_from_dict(
|
|
449
438
|
) -> Any | list[Any]:
|
450
439
|
"""Prompt for a key from a dict, but return the value."""
|
451
440
|
prompt_session = prompt_session or PromptSession()
|
452
|
-
console = console or Console(color_system="truecolor")
|
453
441
|
|
454
442
|
console.print(table, justify="center")
|
455
443
|
|
@@ -457,7 +445,6 @@ async def select_value_from_dict(
|
|
457
445
|
selections.keys(),
|
458
446
|
table,
|
459
447
|
default_selection=default_selection,
|
460
|
-
console=console,
|
461
448
|
prompt_session=prompt_session,
|
462
449
|
prompt_message=prompt_message,
|
463
450
|
number_selections=number_selections,
|
@@ -475,7 +462,6 @@ async def get_selection_from_dict_menu(
|
|
475
462
|
title: str,
|
476
463
|
selections: dict[str, SelectionOption],
|
477
464
|
*,
|
478
|
-
console: Console | None = None,
|
479
465
|
prompt_session: PromptSession | None = None,
|
480
466
|
prompt_message: str = "Select an option > ",
|
481
467
|
default_selection: str = "",
|
@@ -493,7 +479,6 @@ async def get_selection_from_dict_menu(
|
|
493
479
|
return await select_value_from_dict(
|
494
480
|
selections=selections,
|
495
481
|
table=table,
|
496
|
-
console=console,
|
497
482
|
prompt_session=prompt_session,
|
498
483
|
prompt_message=prompt_message,
|
499
484
|
default_selection=default_selection,
|
falyx/validators.py
CHANGED
@@ -47,6 +47,30 @@ def yes_no_validator() -> Validator:
|
|
47
47
|
return Validator.from_callable(validate, error_message="Enter 'Y' or 'n'.")
|
48
48
|
|
49
49
|
|
50
|
+
def words_validator(keys: Sequence[str] | KeysView[str]) -> Validator:
|
51
|
+
"""Validator for specific word inputs."""
|
52
|
+
|
53
|
+
def validate(text: str) -> bool:
|
54
|
+
if text.upper() not in [key.upper() for key in keys]:
|
55
|
+
return False
|
56
|
+
return True
|
57
|
+
|
58
|
+
return Validator.from_callable(
|
59
|
+
validate, error_message=f"Invalid input. Choices: {{{', '.join(keys)}}}."
|
60
|
+
)
|
61
|
+
|
62
|
+
|
63
|
+
def word_validator(word: str) -> Validator:
|
64
|
+
"""Validator for specific word inputs."""
|
65
|
+
|
66
|
+
def validate(text: str) -> bool:
|
67
|
+
if text.upper().strip() == "N":
|
68
|
+
return True
|
69
|
+
return text.upper().strip() == word.upper()
|
70
|
+
|
71
|
+
return Validator.from_callable(validate, error_message=f"Enter '{word}' or 'N'.")
|
72
|
+
|
73
|
+
|
50
74
|
class MultiIndexValidator(Validator):
|
51
75
|
def __init__(
|
52
76
|
self,
|
falyx/version.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = "0.1.
|
1
|
+
__version__ = "0.1.57"
|
@@ -1,67 +1,70 @@
|
|
1
1
|
falyx/.pytyped,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
-
falyx/__init__.py,sha256=
|
2
|
+
falyx/__init__.py,sha256=OnKzXya3kLoQ9lOZ78Jazl12GPQFMda4MgnrJBiFSsc,306
|
3
3
|
falyx/__main__.py,sha256=xHO4pB45rccixo-ougF84QJeB36ef8mEZXWVK_CJL9M,3420
|
4
4
|
falyx/action/.pytyped,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
5
|
-
falyx/action/__init__.py,sha256=
|
5
|
+
falyx/action/__init__.py,sha256=_DfOQkNOCTmtC8DmS4rD4h5Vv9tmf0dab6VVyvvdQWU,1464
|
6
6
|
falyx/action/action.py,sha256=Pm9lnxKhJoI1vs-fadAJrXkcDGYcBCMwvQ81HHxd0HA,5879
|
7
7
|
falyx/action/action_factory.py,sha256=WosLeaYf79e83XHAAkxKi62zi8jJEiVlzvgOC84Z7t0,4840
|
8
|
-
falyx/action/action_group.py,sha256=
|
8
|
+
falyx/action/action_group.py,sha256=RQdHOWCa8XRUme3S5YGJTICLozIApAlIpRUgEeFaiyw,7728
|
9
9
|
falyx/action/action_mixins.py,sha256=oUrjbweCeateshg3tqtbQiGuV8u4GvlioIZCUr9D1m4,1244
|
10
10
|
falyx/action/action_types.py,sha256=oG8qIFObZdiU1VZQlnWzR8uBDq8rcxzkCli9A31_tMI,1460
|
11
|
-
falyx/action/base_action.py,sha256=
|
12
|
-
falyx/action/chained_action.py,sha256=
|
11
|
+
falyx/action/base_action.py,sha256=o9Nml70-SEVTXnu9J0-VYnO-t5wZZM0o59lYDth24Po,5829
|
12
|
+
falyx/action/chained_action.py,sha256=oknG4ACr79Yf7jb4jvpp6Au7VJLz3PRqABzUKJLn_eY,9274
|
13
|
+
falyx/action/confirm_action.py,sha256=HCzDBQMX1I_cquV_26ppKPfB0GJjr24v12kaZ4Q6bSU,8700
|
13
14
|
falyx/action/fallback_action.py,sha256=3FGWfoR1MIgY0ZkDNOpKu8p3JqPWzh5ON3943mfgDGs,1708
|
14
15
|
falyx/action/http_action.py,sha256=DNeSBWh58UTFGlfFyTk2GnhS54hpLAJLC0QNbq2cYic,5799
|
15
16
|
falyx/action/io_action.py,sha256=V888tQgAynqsVvkhICnEeE4wRs2vvdTcdlEpDSEbHqo,6128
|
16
17
|
falyx/action/literal_input_action.py,sha256=ShXXiUYKg01BMZRChlxEWlNcaLXV1B1LW-w5A8mOPvA,1387
|
17
|
-
falyx/action/load_file_action.py,sha256=
|
18
|
-
falyx/action/menu_action.py,sha256=
|
18
|
+
falyx/action/load_file_action.py,sha256=HcwSVWI8-4_dp3VC4iHR3ARaTpY0Y1rChMqpyqQjIGg,8091
|
19
|
+
falyx/action/menu_action.py,sha256=UwMF3Y3v8AWXGCkVpzj_k3pCge5BlJvKhqGYXh_dNCc,5775
|
19
20
|
falyx/action/process_action.py,sha256=nUNcJD6Ms34vmj8njWzv1R1P9xJTyJmelnyJksHcp7M,4666
|
20
21
|
falyx/action/process_pool_action.py,sha256=XeL6e7vsy4OkOWGQHD0ET14CzuyJ0TL-c1W5VIgdCP8,6204
|
21
|
-
falyx/action/prompt_menu_action.py,sha256=
|
22
|
-
falyx/action/save_file_action.py,sha256=
|
23
|
-
falyx/action/select_file_action.py,sha256=
|
24
|
-
falyx/action/selection_action.py,sha256=
|
22
|
+
falyx/action/prompt_menu_action.py,sha256=PTn6US8ql5SU7ilEMVCeoGqKTc31be3AbdCfcrZ6ujU,5034
|
23
|
+
falyx/action/save_file_action.py,sha256=P5gfTUFnmzAK8yJSd4b5GV69G58MxJXgb4H7kXiRteA,9200
|
24
|
+
falyx/action/select_file_action.py,sha256=PcV22_wiPeDoJLIhHRiEUmW8N3pYeqQZMVTscQKXuas,9867
|
25
|
+
falyx/action/selection_action.py,sha256=L1evMm7oAQFGMviZ8nMwFKhWKWe8X7wW6dJPHGxpqAE,15398
|
25
26
|
falyx/action/shell_action.py,sha256=0A_kvZLsYmeLHInMM_4Jpe8GCSnXzGBm7H9PnXPvbAs,4055
|
26
27
|
falyx/action/signal_action.py,sha256=5UMqvzy7fBnLANGwYUWoe1VRhrr7e-yOVeLdOnCBiJo,1350
|
27
|
-
falyx/action/user_input_action.py,sha256=
|
28
|
-
falyx/bottom_bar.py,sha256=
|
29
|
-
falyx/command.py,sha256=
|
30
|
-
falyx/
|
31
|
-
falyx/
|
28
|
+
falyx/action/user_input_action.py,sha256=Up47lumscxnhORMvaft0X-NWpxTXc2GmMZMua__pGhA,3524
|
29
|
+
falyx/bottom_bar.py,sha256=QYAuWWOM_FVObuRrGrZWOYvuvL45cnYDtV34s5B1qFU,7372
|
30
|
+
falyx/command.py,sha256=QdcwLEFIaq3a4Lfot4cV3zHbVJNQxwSpShprBgLBkh8,16891
|
31
|
+
falyx/completer.py,sha256=EODbakx5PFAwjNcfuUZPFuSx2Q9MXBlWRZJ2LejF6DI,1686
|
32
|
+
falyx/config.py,sha256=OFEq9pFhV39o6_D7dP_QUDjqEusSQNpgomRsh5AAZYY,9621
|
33
|
+
falyx/console.py,sha256=WIZ004R9x6DJp2g3onBQ4DOJ7iDeTOr8HqJCwRt30Rc,143
|
34
|
+
falyx/context.py,sha256=SuQxxYuv1cb__EieJyRHp7opO-9T5KsMPxruEjVN36Q,10784
|
32
35
|
falyx/debug.py,sha256=pguI0XQcZ-7jte5YUPexAufa1oxxalYO1JgmO6GU3rI,1557
|
33
36
|
falyx/exceptions.py,sha256=58D4BYkyJ7PlpZoNk37GsUsFThm_gIlb2Ex2XXhLklI,1099
|
34
|
-
falyx/execution_registry.py,sha256=
|
35
|
-
falyx/falyx.py,sha256=
|
36
|
-
falyx/falyx_completer.py,sha256=
|
37
|
+
falyx/execution_registry.py,sha256=RLRMOEmfDElFy4tuC8L9tRyNToX7GJ4GoEBh2Iri8zo,7662
|
38
|
+
falyx/falyx.py,sha256=5pOpYHuw6VZqjC9tszA6wgvahOfxmmIPDtzphcVOVi4,49342
|
39
|
+
falyx/falyx_completer.py,sha256=MsfuZXpfGwbsGG-4Zp-j-vNsNnaote-UAJkJh0s2NZI,5236
|
37
40
|
falyx/hook_manager.py,sha256=TFuHQnAncS_rk6vuw-VSx8bnAppLuHfrZCrzLwqcO9o,2979
|
38
41
|
falyx/hooks.py,sha256=xMfQROib0BNsaQF4AXJpmCiGePoE1f1xpcdibgnVZWM,2913
|
39
|
-
falyx/init.py,sha256=
|
42
|
+
falyx/init.py,sha256=fZ8cvJ9rTGOhvAiAUmA7aPw9FsOUIuobTPW3sz47My8,3287
|
40
43
|
falyx/logger.py,sha256=-qAn6fiqCDDgpx30lYieyA6YyzBTPkrjSKPbdnvIUXU,148
|
41
44
|
falyx/menu.py,sha256=9kvLZhkC8PoSQvv1NZQsPIFSDy11dXfFgqVAuDmtfsM,3752
|
42
45
|
falyx/options_manager.py,sha256=dFAnQw543tQ6Xupvh1PwBrhiSWlSACHw8K-sHP_lUh4,2842
|
43
46
|
falyx/parser/.pytyped,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
44
47
|
falyx/parser/__init__.py,sha256=NbxAovKIY-duFTs6DAsdM_OzL7s3VIu19KMOmltX9ts,512
|
45
|
-
falyx/parser/argument.py,sha256=
|
48
|
+
falyx/parser/argument.py,sha256=piY3edF9rdUtOP343TWTyOq3OuNJWyQA6K9CFy2mrvY,3519
|
46
49
|
falyx/parser/argument_action.py,sha256=rNVeth0eMpkZRU_eT1RPVxOGzD4pbdAMx9Kq07T4mG4,709
|
47
|
-
falyx/parser/command_argument_parser.py,sha256=
|
50
|
+
falyx/parser/command_argument_parser.py,sha256=Ej4gYOxSUOYfLr5b0KkZkC0OkuSUrj54JpuI0D0C6h4,37504
|
48
51
|
falyx/parser/parsers.py,sha256=X3eEltxBbwRwWG5Q1A1GqSdQCJZAYN5Eub0_U6dlBN4,9159
|
49
52
|
falyx/parser/signature.py,sha256=fSltLEr8ctj1qpbU-OvTMnREjlb8OTG5t-guJFR7j4E,2529
|
50
|
-
falyx/parser/utils.py,sha256=
|
53
|
+
falyx/parser/utils.py,sha256=km6WvoPUgVdoIpPwDfr6axyjyy8iZy8xndwBNprI2Lk,2996
|
51
54
|
falyx/prompt_utils.py,sha256=qgk0bXs7mwzflqzWyFhEOTpKQ_ZtMIqGhKeg-ocwNnE,1542
|
52
55
|
falyx/protocols.py,sha256=vd9JL-TXdLEiAQXLw2UKLd3MUMivoG7iMLo08ZggwYQ,539
|
53
56
|
falyx/retry.py,sha256=sGRE9QhdZK98M99G8F15WUsJ_fYLNyLlCgu3UANaSQs,3744
|
54
57
|
falyx/retry_utils.py,sha256=IqvEy_F0dXG8Yl2UoEJVLX-6OXk-dh-D72_SWv4w-p0,730
|
55
|
-
falyx/selection.py,sha256=
|
58
|
+
falyx/selection.py,sha256=Q2GrpiRyuV8KwVrZGuK2WZvihZ0VIylyvckJKYwrC-A,14629
|
56
59
|
falyx/signals.py,sha256=Y_neFXpfHs7qY0syw9XcfR9WeAGRcRw1nG_2L1JJqKE,1083
|
57
60
|
falyx/tagged_table.py,sha256=4SV-SdXFrAhy1JNToeBCvyxT-iWVf6cWY7XETTys4n8,1067
|
58
61
|
falyx/themes/__init__.py,sha256=1CZhEUCin9cUk8IGYBUFkVvdHRNNJBEFXccHwpUKZCA,284
|
59
62
|
falyx/themes/colors.py,sha256=4aaeAHJetmeNInI0Zytg4E3YqKfPFelpf04vtjSvsS8,19776
|
60
63
|
falyx/utils.py,sha256=U45xnZFUdoFC4xiji_9S1jHS5V7MvxSDtufP8EgB0SM,6732
|
61
|
-
falyx/validators.py,sha256=
|
62
|
-
falyx/version.py,sha256=
|
63
|
-
falyx-0.1.
|
64
|
-
falyx-0.1.
|
65
|
-
falyx-0.1.
|
66
|
-
falyx-0.1.
|
67
|
-
falyx-0.1.
|
64
|
+
falyx/validators.py,sha256=DHq-ELpeYVHvRg9daY4Te6ufAf4ryUAM7i_uF7B15Sc,5919
|
65
|
+
falyx/version.py,sha256=4_3hAGEogvYbOy6vn6QDJpHwwyZfPSVQHAgrUMAMbLI,23
|
66
|
+
falyx-0.1.57.dist-info/LICENSE,sha256=B0yqgaHuSdhN7T3OBmgQSiDTy8HqT5Oe_dLypRe4Ra4,1073
|
67
|
+
falyx-0.1.57.dist-info/METADATA,sha256=RREKc2TcwfK9cxUsOnVpqHjovgIDIIZwz1i8jzcXtJk,5561
|
68
|
+
falyx-0.1.57.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
|
69
|
+
falyx-0.1.57.dist-info/entry_points.txt,sha256=j8owOSl2j1Ss8DtGMnKfgehKaolqnIPhVFHaUBLUnMs,45
|
70
|
+
falyx-0.1.57.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|