|
6 | 6 |
|
7 | 7 | # pyre-strict |
8 | 8 |
|
| 9 | +import abc |
9 | 10 | import asyncio |
10 | 11 | import copy |
11 | 12 | import inspect |
|
17 | 18 | import shutil |
18 | 19 | import typing |
19 | 20 | import warnings |
| 21 | +from abc import abstractmethod |
20 | 22 | from dataclasses import asdict, dataclass, field |
21 | 23 | from datetime import datetime |
22 | 24 | from enum import Enum, IntEnum |
|
36 | 38 | Tuple, |
37 | 39 | Type, |
38 | 40 | TypeVar, |
39 | | - Union, |
40 | 41 | ) |
41 | 42 |
|
| 43 | +import parse |
| 44 | + |
42 | 45 | from torchx.util.types import to_dict |
| 46 | +from typing_extensions import Self |
43 | 47 |
|
44 | 48 | _APP_STATUS_FORMAT_TEMPLATE = """AppStatus: |
45 | 49 | State: ${state} |
@@ -877,11 +881,72 @@ def __init__(self, status: AppStatus, *args: object) -> None: |
877 | 881 | self.status = status |
878 | 882 |
|
879 | 883 |
|
880 | | -# valid run cfg values; only support primitives (str, int, float, bool, List[str], Dict[str, str]) |
| 884 | +U = TypeVar("U", bound="StructuredRunOpt") |
| 885 | + |
| 886 | + |
| 887 | +class StructuredRunOpt(abc.ABC): |
| 888 | + """ |
| 889 | + StructuredRunOpt is a class that represents a structured run option. |
| 890 | + This is to allow for more complex types than currently supported. |
| 891 | +
|
| 892 | + Usage |
| 893 | +
|
| 894 | + .. doctest:: |
| 895 | + @dataclass |
| 896 | + class Ulimit(StructuredRunOpt): |
| 897 | + name: str |
| 898 | + hard: int |
| 899 | + soft: int |
| 900 | +
|
| 901 | + def template(self) -> str: |
| 902 | + # The template string should contain the field names of the Ulimit object. |
| 903 | + # Template strings also may need types as below where `:d` is for integer type. |
| 904 | + return "{name},{soft:d},{hard:d}" |
| 905 | +
|
| 906 | + opts = runopts() |
| 907 | + opts.add("ulimit", type_=self.Ulimit, help="ulimits for the container") |
| 908 | +
|
| 909 | + # .from_repr() is used to create a Ulimit object from a string representation that is the template. |
| 910 | + cfg = opts.resolve( |
| 911 | + { |
| 912 | + "ulimit": self.Ulimit.from_repr( |
| 913 | + "test,50,100", |
| 914 | + ) |
| 915 | + } |
| 916 | + ) |
| 917 | +
|
| 918 | + """ |
| 919 | + |
| 920 | + @abstractmethod |
| 921 | + def template(self) -> str: |
| 922 | + """ |
| 923 | + Returns the template string for the StructuredRunOpt. |
| 924 | + These are mapped to the field names of the StructuredRunOpt object. |
| 925 | + """ |
| 926 | + ... |
| 927 | + |
| 928 | + def __repr__(self) -> str: |
| 929 | + return self.template().format(**asdict(self)) |
| 930 | + |
| 931 | + def __eq__(self, other: object) -> bool: |
| 932 | + return isinstance(other, type(self)) and asdict(self) == asdict(other) |
| 933 | + |
| 934 | + @classmethod |
| 935 | + def from_repr(cls, repr: str) -> Self: |
| 936 | + """ |
| 937 | + Parses the repr string and returns a StructuredRunOpt object |
| 938 | + """ |
| 939 | + tmpl = cls.__new__(cls).template() |
| 940 | + result = parse.parse(tmpl, repr) |
| 941 | + return cls(**result.named) |
| 942 | + |
| 943 | + |
| 944 | +# valid run cfg values; support primitives (str, int, float, bool, List[str], Dict[str, str]) |
| 945 | +# And StructuredRunOpt Type for more complex types. |
881 | 946 | # TODO(wilsonhong): python 3.9+ supports list[T] in typing, which can be used directly |
882 | 947 | # in isinstance(). Should replace with that. |
883 | 948 | # see: https://docs.python.org/3/library/stdtypes.html#generic-alias-type |
884 | | -CfgVal = Union[str, int, float, bool, List[str], Dict[str, str], None] |
| 949 | +CfgVal = str | int | float | bool | List[str] | Dict[str, str] | StructuredRunOpt | None |
885 | 950 |
|
886 | 951 |
|
887 | 952 | T = TypeVar("T") |
|
0 commit comments