| 796 | """"More flexible argument parser.""" |
| 797 | |
| 798 | def parse_args(self, args=None, namespace=None): |
| 799 | # If args is not provided, use arguments from the command line |
| 800 | if args is None: |
| 801 | args = sys.argv[1:] |
| 802 | |
| 803 | def repl(match: re.Match) -> str: |
| 804 | """Replaces underscores with dashes in the matched string.""" |
| 805 | return match.group(0).replace('_', '-') |
| 806 | |
| 807 | # Everything between the first -- and the first . |
| 808 | pattern = re.compile(r'(?<=--)[^\.]*') |
| 809 | |
| 810 | # Convert underscores to dashes and vice versa in argument names |
| 811 | processed_args = [] |
| 812 | for arg in args: |
| 813 | if arg.startswith('--'): |
| 814 | if '=' in arg: |
| 815 | key, value = arg.split('=', 1) |
| 816 | key = pattern.sub(repl, key, count=1) |
| 817 | processed_args.append(f'{key}={value}') |
| 818 | else: |
| 819 | key = pattern.sub(repl, arg, count=1) |
| 820 | processed_args.append(key) |
| 821 | elif arg.startswith('-O') and arg != '-O' and len(arg) == 2: |
| 822 | # allow -O flag to be used without space, e.g. -O3 |
| 823 | processed_args.append('-O') |
| 824 | processed_args.append(arg[2:]) |
| 825 | else: |
| 826 | processed_args.append(arg) |
| 827 | |
| 828 | def _try_convert(value: str): |
| 829 | """Try to convert string to float or int.""" |
| 830 | if not isinstance(value, str): |
| 831 | return value |
| 832 | # try loads from json |
| 833 | try: |
| 834 | return json.loads(value) |
| 835 | except json.JSONDecodeError: |
| 836 | pass |
| 837 | return value |
| 838 | |
| 839 | def create_nested_dict(keys: list[str], value: str): |
| 840 | """Creates a nested dictionary from a list of keys and a value. |
| 841 | |
| 842 | For example, `keys = ["a", "b", "c"]` and `value = 1` will create: `{"a": {"b": {"c": 1}}}` |
| 843 | """ |
| 844 | nested_dict: Any = _try_convert(value) |
| 845 | for key in reversed(keys): |
| 846 | nested_dict = {key: nested_dict} |
| 847 | return nested_dict |
| 848 | |
| 849 | def recursive_dict_update(original: dict, update: dict): |
| 850 | """Recursively updates a dictionary with another dictionary.""" |
| 851 | for k, v in update.items(): |
| 852 | if isinstance(v, dict) and isinstance(original.get(k), dict): |
| 853 | recursive_dict_update(original[k], v) |
| 854 | else: |
| 855 | original[k] = v |