dataclass-args 1.4.0__tar.gz → 1.4.2__tar.gz
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.
- {dataclass_args-1.4.0 → dataclass_args-1.4.2}/PKG-INFO +1 -1
- {dataclass_args-1.4.0 → dataclass_args-1.4.2}/dataclass_args/__init__.py +1 -1
- {dataclass_args-1.4.0 → dataclass_args-1.4.2}/dataclass_args/annotations.py +71 -199
- {dataclass_args-1.4.0 → dataclass_args-1.4.2}/dataclass_args/builder.py +189 -436
- dataclass_args-1.4.2/dataclass_args/config_applicator.py +142 -0
- dataclass_args-1.4.2/dataclass_args/nested_processor.py +347 -0
- dataclass_args-1.4.2/dataclass_args/type_inspector.py +196 -0
- {dataclass_args-1.4.0 → dataclass_args-1.4.2}/dataclass_args.egg-info/PKG-INFO +1 -1
- {dataclass_args-1.4.0 → dataclass_args-1.4.2}/dataclass_args.egg-info/SOURCES.txt +8 -0
- {dataclass_args-1.4.0 → dataclass_args-1.4.2}/pyproject.toml +1 -1
- dataclass_args-1.4.2/tests/test_collisions.py +183 -0
- dataclass_args-1.4.2/tests/test_config_applicator.py +202 -0
- dataclass_args-1.4.2/tests/test_nested_dict_override.py +240 -0
- dataclass_args-1.4.2/tests/test_nested_property_override_bug.py +176 -0
- dataclass_args-1.4.2/tests/test_type_inspector.py +168 -0
- {dataclass_args-1.4.0 → dataclass_args-1.4.2}/LICENSE +0 -0
- {dataclass_args-1.4.0 → dataclass_args-1.4.2}/README.md +0 -0
- {dataclass_args-1.4.0 → dataclass_args-1.4.2}/dataclass_args/append_action.py +0 -0
- {dataclass_args-1.4.0 → dataclass_args-1.4.2}/dataclass_args/exceptions.py +0 -0
- {dataclass_args-1.4.0 → dataclass_args-1.4.2}/dataclass_args/file_loading.py +0 -0
- {dataclass_args-1.4.0 → dataclass_args-1.4.2}/dataclass_args/formatter.py +0 -0
- {dataclass_args-1.4.0 → dataclass_args-1.4.2}/dataclass_args/utils.py +0 -0
- {dataclass_args-1.4.0 → dataclass_args-1.4.2}/dataclass_args.egg-info/dependency_links.txt +0 -0
- {dataclass_args-1.4.0 → dataclass_args-1.4.2}/dataclass_args.egg-info/requires.txt +0 -0
- {dataclass_args-1.4.0 → dataclass_args-1.4.2}/dataclass_args.egg-info/top_level.txt +0 -0
- {dataclass_args-1.4.0 → dataclass_args-1.4.2}/setup.cfg +0 -0
- {dataclass_args-1.4.0 → dataclass_args-1.4.2}/tests/test_annotations.py +0 -0
- {dataclass_args-1.4.0 → dataclass_args-1.4.2}/tests/test_basic.py +0 -0
- {dataclass_args-1.4.0 → dataclass_args-1.4.2}/tests/test_boolean_base_configs.py +0 -0
- {dataclass_args-1.4.0 → dataclass_args-1.4.2}/tests/test_boolean_flags.py +0 -0
- {dataclass_args-1.4.0 → dataclass_args-1.4.2}/tests/test_builder_advanced.py +0 -0
- {dataclass_args-1.4.0 → dataclass_args-1.4.2}/tests/test_cli_append.py +0 -0
- {dataclass_args-1.4.0 → dataclass_args-1.4.2}/tests/test_cli_choices.py +0 -0
- {dataclass_args-1.4.0 → dataclass_args-1.4.2}/tests/test_cli_nested.py +0 -0
- {dataclass_args-1.4.0 → dataclass_args-1.4.2}/tests/test_cli_short.py +0 -0
- {dataclass_args-1.4.0 → dataclass_args-1.4.2}/tests/test_combine_annotations.py +0 -0
- {dataclass_args-1.4.0 → dataclass_args-1.4.2}/tests/test_config_merging_simple.py +0 -0
- {dataclass_args-1.4.0 → dataclass_args-1.4.2}/tests/test_description.py +0 -0
- {dataclass_args-1.4.0 → dataclass_args-1.4.2}/tests/test_file_loading.py +0 -0
- {dataclass_args-1.4.0 → dataclass_args-1.4.2}/tests/test_positional.py +0 -0
- {dataclass_args-1.4.0 → dataclass_args-1.4.2}/tests/test_utils.py +0 -0
|
@@ -91,7 +91,7 @@ from .exceptions import ConfigBuilderError, ConfigurationError, FileLoadingError
|
|
|
91
91
|
from .file_loading import is_file_loadable_value, load_file_content
|
|
92
92
|
from .utils import load_structured_file
|
|
93
93
|
|
|
94
|
-
__version__ = "1.4.
|
|
94
|
+
__version__ = "1.4.2"
|
|
95
95
|
|
|
96
96
|
__all__ = [
|
|
97
97
|
# Main API
|
|
@@ -8,6 +8,47 @@ be excluded from CLI argument generation or have special behaviors.
|
|
|
8
8
|
from dataclasses import field
|
|
9
9
|
from typing import Any, Dict, List, Optional
|
|
10
10
|
|
|
11
|
+
# ============================================================================
|
|
12
|
+
# Unified Metadata Accessor
|
|
13
|
+
# ============================================================================
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class _FieldMetadata:
|
|
17
|
+
"""
|
|
18
|
+
Unified accessor for field metadata.
|
|
19
|
+
|
|
20
|
+
Internal class that eliminates duplication across all get_cli_* and is_cli_* functions.
|
|
21
|
+
All these functions share the same pattern: extract field_obj, check metadata, return value.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
@staticmethod
|
|
25
|
+
def get(field_info: Dict[str, Any], key: str, default: Any = None) -> Any:
|
|
26
|
+
"""
|
|
27
|
+
Get metadata value from field_info dict.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
field_info: Field information dictionary from GenericConfigBuilder
|
|
31
|
+
key: Metadata key to retrieve
|
|
32
|
+
default: Default value if key not found
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
Metadata value or default
|
|
36
|
+
"""
|
|
37
|
+
field_obj = field_info.get("field_obj")
|
|
38
|
+
if field_obj and hasattr(field_obj, "metadata"):
|
|
39
|
+
return field_obj.metadata.get(key, default)
|
|
40
|
+
return default
|
|
41
|
+
|
|
42
|
+
@staticmethod
|
|
43
|
+
def get_bool(field_info: Dict[str, Any], key: str) -> bool:
|
|
44
|
+
"""Get boolean metadata value (defaults to False)."""
|
|
45
|
+
return _FieldMetadata.get(field_info, key, False)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
# ============================================================================
|
|
49
|
+
# CLI Annotation Decorators
|
|
50
|
+
# ============================================================================
|
|
51
|
+
|
|
11
52
|
|
|
12
53
|
def cli_exclude(**kwargs) -> Any:
|
|
13
54
|
"""
|
|
@@ -595,261 +636,92 @@ def cli_positional(
|
|
|
595
636
|
|
|
596
637
|
|
|
597
638
|
def is_cli_excluded(field_info: Dict[str, Any]) -> bool:
|
|
598
|
-
"""
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
Args:
|
|
602
|
-
field_info: Field information dictionary from GenericConfigBuilder
|
|
603
|
-
|
|
604
|
-
Returns:
|
|
605
|
-
True if field should be excluded from CLI
|
|
606
|
-
"""
|
|
607
|
-
# Check for explicit CLI exclusion metadata
|
|
608
|
-
field_obj = field_info.get("field_obj")
|
|
609
|
-
if field_obj and hasattr(field_obj, "metadata"):
|
|
610
|
-
return field_obj.metadata.get("cli_exclude", False)
|
|
611
|
-
|
|
612
|
-
return False
|
|
639
|
+
"""Check if a field should be excluded from CLI arguments."""
|
|
640
|
+
return _FieldMetadata.get_bool(field_info, "cli_exclude")
|
|
613
641
|
|
|
614
642
|
|
|
615
643
|
def is_cli_included(field_info: Dict[str, Any]) -> bool:
|
|
616
|
-
"""
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
Args:
|
|
620
|
-
field_info: Field information dictionary from GenericConfigBuilder
|
|
621
|
-
|
|
622
|
-
Returns:
|
|
623
|
-
True if field is explicitly marked for CLI inclusion
|
|
624
|
-
"""
|
|
625
|
-
field_obj = field_info.get("field_obj")
|
|
626
|
-
if field_obj and hasattr(field_obj, "metadata"):
|
|
627
|
-
return field_obj.metadata.get("cli_include", False)
|
|
628
|
-
|
|
629
|
-
return False
|
|
644
|
+
"""Check if a field is explicitly marked for CLI inclusion."""
|
|
645
|
+
return _FieldMetadata.get_bool(field_info, "cli_include")
|
|
630
646
|
|
|
631
647
|
|
|
632
648
|
def is_cli_nested(field_info: Dict[str, Any]) -> bool:
|
|
633
|
-
"""
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
Args:
|
|
637
|
-
field_info: Field information dictionary from GenericConfigBuilder
|
|
638
|
-
|
|
639
|
-
Returns:
|
|
640
|
-
True if field should be flattened as nested dataclass
|
|
641
|
-
"""
|
|
642
|
-
field_obj = field_info.get("field_obj")
|
|
643
|
-
if field_obj and hasattr(field_obj, "metadata"):
|
|
644
|
-
return field_obj.metadata.get("cli_nested", False)
|
|
645
|
-
return False
|
|
649
|
+
"""Check if a field is marked for nested dataclass flattening."""
|
|
650
|
+
return _FieldMetadata.get_bool(field_info, "cli_nested")
|
|
646
651
|
|
|
647
652
|
|
|
648
653
|
def get_cli_nested_prefix(field_info: Dict[str, Any]) -> Optional[str]:
|
|
649
654
|
"""
|
|
650
655
|
Get prefix for nested dataclass CLI arguments.
|
|
651
656
|
|
|
652
|
-
Args:
|
|
653
|
-
field_info: Field information dictionary from GenericConfigBuilder
|
|
654
|
-
|
|
655
657
|
Returns:
|
|
656
|
-
Prefix string if specified:
|
|
657
658
|
- "" (empty string): No prefix
|
|
658
659
|
- "custom": Custom prefix
|
|
659
660
|
- None: Auto-prefix with field name (default)
|
|
660
661
|
"""
|
|
661
|
-
|
|
662
|
-
if field_obj and hasattr(field_obj, "metadata"):
|
|
663
|
-
return field_obj.metadata.get("cli_nested_prefix")
|
|
664
|
-
return None
|
|
662
|
+
return _FieldMetadata.get(field_info, "cli_nested_prefix")
|
|
665
663
|
|
|
666
664
|
|
|
667
665
|
def is_cli_file_loadable(field_info: Dict[str, Any]) -> bool:
|
|
668
|
-
"""
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
Args:
|
|
672
|
-
field_info: Field information dictionary from GenericConfigBuilder
|
|
673
|
-
|
|
674
|
-
Returns:
|
|
675
|
-
True if field supports file loading via '@' prefix
|
|
676
|
-
"""
|
|
677
|
-
field_obj = field_info.get("field_obj")
|
|
678
|
-
if field_obj and hasattr(field_obj, "metadata"):
|
|
679
|
-
return field_obj.metadata.get("cli_file_loadable", False)
|
|
680
|
-
|
|
681
|
-
return False
|
|
666
|
+
"""Check if a field is marked as file-loadable via '@' prefix."""
|
|
667
|
+
return _FieldMetadata.get_bool(field_info, "cli_file_loadable")
|
|
682
668
|
|
|
683
669
|
|
|
684
670
|
def is_cli_append(field_info: Dict[str, Any]) -> bool:
|
|
685
|
-
"""
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
Args:
|
|
689
|
-
field_info: Field information dictionary from GenericConfigBuilder
|
|
690
|
-
|
|
691
|
-
Returns:
|
|
692
|
-
True if field uses append action
|
|
693
|
-
"""
|
|
694
|
-
field_obj = field_info.get("field_obj")
|
|
695
|
-
if field_obj and hasattr(field_obj, "metadata"):
|
|
696
|
-
return field_obj.metadata.get("cli_append", False)
|
|
697
|
-
return False
|
|
671
|
+
"""Check if a field uses append action for repeated options."""
|
|
672
|
+
return _FieldMetadata.get_bool(field_info, "cli_append")
|
|
698
673
|
|
|
699
674
|
|
|
700
675
|
def is_cli_positional(field_info: Dict[str, Any]) -> bool:
|
|
701
|
-
"""
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
Args:
|
|
705
|
-
field_info: Field information dictionary from GenericConfigBuilder
|
|
706
|
-
|
|
707
|
-
Returns:
|
|
708
|
-
True if field is a positional argument
|
|
709
|
-
"""
|
|
710
|
-
field_obj = field_info.get("field_obj")
|
|
711
|
-
if field_obj and hasattr(field_obj, "metadata"):
|
|
712
|
-
return field_obj.metadata.get("cli_positional", False)
|
|
713
|
-
return False
|
|
676
|
+
"""Check if a field is marked as a positional CLI argument."""
|
|
677
|
+
return _FieldMetadata.get_bool(field_info, "cli_positional")
|
|
714
678
|
|
|
715
679
|
|
|
716
680
|
def get_cli_short(field_info: Dict[str, Any]) -> Optional[str]:
|
|
717
|
-
"""
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
Args:
|
|
721
|
-
field_info: Field information dictionary from GenericConfigBuilder
|
|
722
|
-
|
|
723
|
-
Returns:
|
|
724
|
-
Short option character if available, otherwise None
|
|
725
|
-
"""
|
|
726
|
-
field_obj = field_info.get("field_obj")
|
|
727
|
-
if field_obj and hasattr(field_obj, "metadata"):
|
|
728
|
-
return field_obj.metadata.get("cli_short")
|
|
729
|
-
return None
|
|
681
|
+
"""Get short option character for a CLI argument."""
|
|
682
|
+
return _FieldMetadata.get(field_info, "cli_short")
|
|
730
683
|
|
|
731
684
|
|
|
732
685
|
def get_cli_choices(field_info: Dict[str, Any]) -> Optional[List[Any]]:
|
|
733
|
-
"""
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
Args:
|
|
737
|
-
field_info: Field information dictionary from GenericConfigBuilder
|
|
738
|
-
|
|
739
|
-
Returns:
|
|
740
|
-
List of valid choices if available, otherwise None
|
|
741
|
-
"""
|
|
742
|
-
field_obj = field_info.get("field_obj")
|
|
743
|
-
if field_obj and hasattr(field_obj, "metadata"):
|
|
744
|
-
return field_obj.metadata.get("cli_choices")
|
|
745
|
-
return None
|
|
686
|
+
"""Get restricted choices for a CLI argument."""
|
|
687
|
+
return _FieldMetadata.get(field_info, "cli_choices")
|
|
746
688
|
|
|
747
689
|
|
|
748
690
|
def get_cli_append_nargs(field_info: Dict[str, Any]) -> Optional[Any]:
|
|
749
|
-
"""
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
Args:
|
|
753
|
-
field_info: Field information dictionary from GenericConfigBuilder
|
|
754
|
-
|
|
755
|
-
Returns:
|
|
756
|
-
nargs value if specified, otherwise None (meaning exactly one per occurrence)
|
|
757
|
-
"""
|
|
758
|
-
field_obj = field_info.get("field_obj")
|
|
759
|
-
if field_obj and hasattr(field_obj, "metadata"):
|
|
760
|
-
return field_obj.metadata.get("cli_append_nargs")
|
|
761
|
-
return None
|
|
691
|
+
"""Get nargs value for an append CLI argument."""
|
|
692
|
+
return _FieldMetadata.get(field_info, "cli_append_nargs")
|
|
762
693
|
|
|
763
694
|
|
|
764
695
|
def get_cli_append_metavar(field_info: Dict[str, Any]) -> Optional[str]:
|
|
765
|
-
"""
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
Args:
|
|
769
|
-
field_info: Field information dictionary from GenericConfigBuilder
|
|
770
|
-
|
|
771
|
-
Returns:
|
|
772
|
-
Metavar string if specified, otherwise None
|
|
773
|
-
"""
|
|
774
|
-
field_obj = field_info.get("field_obj")
|
|
775
|
-
if field_obj and hasattr(field_obj, "metadata"):
|
|
776
|
-
return field_obj.metadata.get("cli_append_metavar")
|
|
777
|
-
return None
|
|
696
|
+
"""Get metavar for an append CLI argument."""
|
|
697
|
+
return _FieldMetadata.get(field_info, "cli_append_metavar")
|
|
778
698
|
|
|
779
699
|
|
|
780
700
|
def get_cli_append_min_args(field_info: Dict[str, Any]) -> Optional[int]:
|
|
781
|
-
"""
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
Args:
|
|
785
|
-
field_info: Field information dictionary from GenericConfigBuilder
|
|
786
|
-
|
|
787
|
-
Returns:
|
|
788
|
-
Minimum argument count if specified, otherwise None
|
|
789
|
-
"""
|
|
790
|
-
field_obj = field_info.get("field_obj")
|
|
791
|
-
if field_obj and hasattr(field_obj, "metadata"):
|
|
792
|
-
return field_obj.metadata.get("cli_append_min_args")
|
|
793
|
-
return None
|
|
701
|
+
"""Get minimum arguments for an append CLI argument."""
|
|
702
|
+
return _FieldMetadata.get(field_info, "cli_append_min_args")
|
|
794
703
|
|
|
795
704
|
|
|
796
705
|
def get_cli_append_max_args(field_info: Dict[str, Any]) -> Optional[int]:
|
|
797
|
-
"""
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
Args:
|
|
801
|
-
field_info: Field information dictionary from GenericConfigBuilder
|
|
802
|
-
|
|
803
|
-
Returns:
|
|
804
|
-
Maximum argument count if specified, otherwise None
|
|
805
|
-
"""
|
|
806
|
-
field_obj = field_info.get("field_obj")
|
|
807
|
-
if field_obj and hasattr(field_obj, "metadata"):
|
|
808
|
-
return field_obj.metadata.get("cli_append_max_args")
|
|
809
|
-
return None
|
|
706
|
+
"""Get maximum arguments for an append CLI argument."""
|
|
707
|
+
return _FieldMetadata.get(field_info, "cli_append_max_args")
|
|
810
708
|
|
|
811
709
|
|
|
812
710
|
def get_cli_positional_nargs(field_info: Dict[str, Any]) -> Optional[Any]:
|
|
813
|
-
"""
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
Args:
|
|
817
|
-
field_info: Field information dictionary from GenericConfigBuilder
|
|
818
|
-
|
|
819
|
-
Returns:
|
|
820
|
-
nargs value if specified, otherwise None (meaning exactly one)
|
|
821
|
-
"""
|
|
822
|
-
field_obj = field_info.get("field_obj")
|
|
823
|
-
if field_obj and hasattr(field_obj, "metadata"):
|
|
824
|
-
return field_obj.metadata.get("cli_positional_nargs")
|
|
825
|
-
return None
|
|
711
|
+
"""Get nargs value for a positional CLI argument."""
|
|
712
|
+
return _FieldMetadata.get(field_info, "cli_positional_nargs")
|
|
826
713
|
|
|
827
714
|
|
|
828
715
|
def get_cli_positional_metavar(field_info: Dict[str, Any]) -> Optional[str]:
|
|
829
|
-
"""
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
Args:
|
|
833
|
-
field_info: Field information dictionary from GenericConfigBuilder
|
|
834
|
-
|
|
835
|
-
Returns:
|
|
836
|
-
Metavar string if specified, otherwise None
|
|
837
|
-
"""
|
|
838
|
-
field_obj = field_info.get("field_obj")
|
|
839
|
-
if field_obj and hasattr(field_obj, "metadata"):
|
|
840
|
-
return field_obj.metadata.get("cli_positional_metavar")
|
|
841
|
-
return None
|
|
716
|
+
"""Get metavar for a positional CLI argument."""
|
|
717
|
+
return _FieldMetadata.get(field_info, "cli_positional_metavar")
|
|
842
718
|
|
|
843
719
|
|
|
844
720
|
def get_cli_help(field_info: Dict[str, Any]) -> str:
|
|
845
721
|
"""
|
|
846
722
|
Get custom help text for a CLI argument.
|
|
847
723
|
|
|
848
|
-
|
|
849
|
-
field_info: Field information dictionary from GenericConfigBuilder
|
|
850
|
-
|
|
851
|
-
Returns:
|
|
852
|
-
Custom help text if available, otherwise empty string
|
|
724
|
+
Automatically adds file-loadable hint if applicable.
|
|
853
725
|
"""
|
|
854
726
|
field_obj = field_info.get("field_obj")
|
|
855
727
|
if field_obj and hasattr(field_obj, "metadata"):
|