str-to-obj 2024.1__py3-none-any.whl → 2024.2__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.
@@ -0,0 +1,73 @@
1
+ # Copyright CNRS/Inria/UniCA
2
+ # Contributor(s): Eric Debreuve (since 2023)
3
+ #
4
+ # eric.debreuve@cnrs.fr
5
+ #
6
+ # This software is governed by the CeCILL license under French law and
7
+ # abiding by the rules of distribution of free software. You can use,
8
+ # modify and/ or redistribute the software under the terms of the CeCILL
9
+ # license as circulated by CEA, CNRS and INRIA at the following URL
10
+ # "http://www.cecill.info".
11
+ #
12
+ # As a counterpart to the access to the source code and rights to copy,
13
+ # modify and redistribute granted by the license, users are provided only
14
+ # with a limited warranty and the software's author, the holder of the
15
+ # economic rights, and the successive licensors have only limited
16
+ # liability.
17
+ #
18
+ # In this respect, the user's attention is drawn to the risks associated
19
+ # with loading, using, modifying and/or developing or reproducing the
20
+ # software by the user in light of its specific status of free software,
21
+ # that may mean that it is complicated to manipulate, and that also
22
+ # therefore means that it is reserved for developers and experienced
23
+ # professionals having in-depth computer knowledge. Users are therefore
24
+ # encouraged to load and test the software's suitability as regards their
25
+ # requirements in conditions enabling the security of their systems and/or
26
+ # data to be ensured and, more generally, to use and operate it in the
27
+ # same conditions as regards security.
28
+ #
29
+ # The fact that you are presently reading this means that you have had
30
+ # knowledge of the CeCILL license and that you accept its terms.
31
+
32
+ import dataclasses as dtcl
33
+ import typing as h
34
+ from enum import Enum as enum_t
35
+
36
+ from str_to_obj import annotation_t
37
+ from str_to_obj.type.hint import annotated_hint_t
38
+
39
+
40
+ class boolean_mode_e(enum_t):
41
+ # Always list true value first.
42
+ true_false = ("True", "False")
43
+ yes_no = ("Yes", "No")
44
+ on_off = ("On", "Off")
45
+
46
+
47
+ _BOOLEAN_MODES = tuple(boolean_mode_e.__members__.keys())
48
+
49
+
50
+ @dtcl.dataclass(slots=True, repr=False, eq=False)
51
+ class boolean_t(annotation_t):
52
+
53
+ ACCEPTED_TYPES: h.ClassVar[tuple[type, ...]] = (bool,)
54
+
55
+ mode: boolean_mode_e = boolean_mode_e.true_false
56
+
57
+ @classmethod
58
+ def NewAnnotatedType(
59
+ cls, /, *, mode: boolean_mode_e | str | None = None
60
+ ) -> annotated_hint_t:
61
+ """"""
62
+ if mode is None:
63
+ mode = boolean_mode_e.true_false
64
+ elif isinstance(mode, str):
65
+ if mode in _BOOLEAN_MODES:
66
+ mode = boolean_mode_e[mode].value
67
+ else:
68
+ valid = " or ".join(_BOOLEAN_MODES)
69
+ raise ValueError(
70
+ f"Invalid boolean mode: Actual={mode}; Expected={valid}."
71
+ )
72
+
73
+ return h.Annotated[bool, cls(mode=mode)]
@@ -0,0 +1,75 @@
1
+ # Copyright CNRS/Inria/UniCA
2
+ # Contributor(s): Eric Debreuve (since 2023)
3
+ #
4
+ # eric.debreuve@cnrs.fr
5
+ #
6
+ # This software is governed by the CeCILL license under French law and
7
+ # abiding by the rules of distribution of free software. You can use,
8
+ # modify and/ or redistribute the software under the terms of the CeCILL
9
+ # license as circulated by CEA, CNRS and INRIA at the following URL
10
+ # "http://www.cecill.info".
11
+ #
12
+ # As a counterpart to the access to the source code and rights to copy,
13
+ # modify and redistribute granted by the license, users are provided only
14
+ # with a limited warranty and the software's author, the holder of the
15
+ # economic rights, and the successive licensors have only limited
16
+ # liability.
17
+ #
18
+ # In this respect, the user's attention is drawn to the risks associated
19
+ # with loading, using, modifying and/or developing or reproducing the
20
+ # software by the user in light of its specific status of free software,
21
+ # that may mean that it is complicated to manipulate, and that also
22
+ # therefore means that it is reserved for developers and experienced
23
+ # professionals having in-depth computer knowledge. Users are therefore
24
+ # encouraged to load and test the software's suitability as regards their
25
+ # requirements in conditions enabling the security of their systems and/or
26
+ # data to be ensured and, more generally, to use and operate it in the
27
+ # same conditions as regards security.
28
+ #
29
+ # The fact that you are presently reading this means that you have had
30
+ # knowledge of the CeCILL license and that you accept its terms.
31
+
32
+ import dataclasses as dtcl
33
+ import typing as h
34
+
35
+ from str_to_obj import annotation_t
36
+ from str_to_obj.catalog.choices import choices_t
37
+ from str_to_obj.type.hint import annotated_hint_t
38
+
39
+
40
+ @dtcl.dataclass(slots=True, repr=False, eq=False)
41
+ class callable_t(annotation_t):
42
+ ACCEPTED_TYPES: h.ClassVar[tuple[type, ...]] = (str,)
43
+ DUMMY_ENTRY: h.ClassVar[str] = "Dummy entry"
44
+ SEPARATOR: h.ClassVar[str] = ":"
45
+ kind: h.Literal["class", "function"]
46
+ choices: choices_t | None = None
47
+ allow_external: bool = False
48
+
49
+ @classmethod
50
+ def NewAnnotatedType(
51
+ cls,
52
+ /,
53
+ *,
54
+ kind: h.Literal["class", "function"] = "function",
55
+ catalog: h.Sequence[str] | bool | None = None,
56
+ allow_external: bool = False,
57
+ ) -> annotated_hint_t:
58
+ """"""
59
+ if catalog is None:
60
+ annotation = cls(kind=kind, allow_external=allow_external)
61
+ elif isinstance(catalog, bool):
62
+ if catalog:
63
+ annotation = cls(
64
+ kind=kind,
65
+ choices=choices_t((cls.DUMMY_ENTRY,)),
66
+ allow_external=allow_external,
67
+ )
68
+ else:
69
+ annotation = cls(kind=kind, allow_external=allow_external)
70
+ else:
71
+ annotation = cls(
72
+ kind=kind, choices=choices_t(catalog), allow_external=allow_external
73
+ )
74
+
75
+ return h.Annotated[str, annotation]
@@ -0,0 +1,76 @@
1
+ # Copyright CNRS/Inria/UniCA
2
+ # Contributor(s): Eric Debreuve (since 2023)
3
+ #
4
+ # eric.debreuve@cnrs.fr
5
+ #
6
+ # This software is governed by the CeCILL license under French law and
7
+ # abiding by the rules of distribution of free software. You can use,
8
+ # modify and/ or redistribute the software under the terms of the CeCILL
9
+ # license as circulated by CEA, CNRS and INRIA at the following URL
10
+ # "http://www.cecill.info".
11
+ #
12
+ # As a counterpart to the access to the source code and rights to copy,
13
+ # modify and redistribute granted by the license, users are provided only
14
+ # with a limited warranty and the software's author, the holder of the
15
+ # economic rights, and the successive licensors have only limited
16
+ # liability.
17
+ #
18
+ # In this respect, the user's attention is drawn to the risks associated
19
+ # with loading, using, modifying and/or developing or reproducing the
20
+ # software by the user in light of its specific status of free software,
21
+ # that may mean that it is complicated to manipulate, and that also
22
+ # therefore means that it is reserved for developers and experienced
23
+ # professionals having in-depth computer knowledge. Users are therefore
24
+ # encouraged to load and test the software's suitability as regards their
25
+ # requirements in conditions enabling the security of their systems and/or
26
+ # data to be ensured and, more generally, to use and operate it in the
27
+ # same conditions as regards security.
28
+ #
29
+ # The fact that you are presently reading this means that you have had
30
+ # knowledge of the CeCILL license and that you accept its terms.
31
+
32
+ import dataclasses as dtcl
33
+ import typing as h
34
+
35
+ from issue_manager import ISSUE_MANAGER
36
+ from str_to_obj import annotation_t
37
+ from str_to_obj.type.hint import annotated_hint_t
38
+
39
+
40
+ @dtcl.dataclass(slots=True, repr=False, eq=False)
41
+ class choices_t(annotation_t):
42
+ ACCEPTED_TYPES: h.ClassVar[tuple[type, ...]] = (str,)
43
+ options: h.Sequence[str]
44
+
45
+ def __post_init__(self) -> None:
46
+ """"""
47
+ with ISSUE_MANAGER.AddedContextLevel("Choices Annotation"):
48
+ for option in self.options:
49
+ if not isinstance(option, str):
50
+ ISSUE_MANAGER.Add(
51
+ f'Invalid type of option "{option}"',
52
+ actual=type(option).__name__,
53
+ expected="str",
54
+ )
55
+
56
+ @classmethod
57
+ def NewAnnotatedType(cls, options: h.Sequence[str], /) -> annotated_hint_t:
58
+ """"""
59
+ return h.Annotated[str, cls(tuple(options))]
60
+
61
+ def ValueIssues(self, value: str | h.Any, /) -> list[str]:
62
+ """"""
63
+ issues = annotation_t.ValueIssues(self, value)
64
+ if issues.__len__() > 0:
65
+ return issues
66
+
67
+ if (self.options.__len__() == 0) or (value in self.options):
68
+ # Options can be empty for a controlling parameter whose controlled section
69
+ # has not been specified. In a GUI context, such controlled section should
70
+ # have been populated programmatically.
71
+ return []
72
+
73
+ options = map(lambda _elm: f'"{_elm}"', self.options)
74
+ options = " or ".join(options)
75
+
76
+ return [f"Invalid choice: Actual={value}; Expected={options}."]
@@ -0,0 +1,154 @@
1
+ # Copyright CNRS/Inria/UniCA
2
+ # Contributor(s): Eric Debreuve (since 2023)
3
+ #
4
+ # eric.debreuve@cnrs.fr
5
+ #
6
+ # This software is governed by the CeCILL license under French law and
7
+ # abiding by the rules of distribution of free software. You can use,
8
+ # modify and/ or redistribute the software under the terms of the CeCILL
9
+ # license as circulated by CEA, CNRS and INRIA at the following URL
10
+ # "http://www.cecill.info".
11
+ #
12
+ # As a counterpart to the access to the source code and rights to copy,
13
+ # modify and redistribute granted by the license, users are provided only
14
+ # with a limited warranty and the software's author, the holder of the
15
+ # economic rights, and the successive licensors have only limited
16
+ # liability.
17
+ #
18
+ # In this respect, the user's attention is drawn to the risks associated
19
+ # with loading, using, modifying and/or developing or reproducing the
20
+ # software by the user in light of its specific status of free software,
21
+ # that may mean that it is complicated to manipulate, and that also
22
+ # therefore means that it is reserved for developers and experienced
23
+ # professionals having in-depth computer knowledge. Users are therefore
24
+ # encouraged to load and test the software's suitability as regards their
25
+ # requirements in conditions enabling the security of their systems and/or
26
+ # data to be ensured and, more generally, to use and operate it in the
27
+ # same conditions as regards security.
28
+ #
29
+ # The fact that you are presently reading this means that you have had
30
+ # knowledge of the CeCILL license and that you accept its terms.
31
+
32
+ from __future__ import annotations
33
+
34
+ import dataclasses as dtcl
35
+ import types as t
36
+ import typing as h
37
+
38
+ from issue_manager import ISSUE_MANAGER
39
+ from str_to_obj import annotation_t
40
+ from str_to_obj.type.hint import any_hint_h
41
+ from str_to_obj.type.type import type_t
42
+
43
+
44
+ @dtcl.dataclass(slots=True, repr=False, eq=False)
45
+ class collection_t(annotation_t):
46
+ # Items of any type but None
47
+ ANY_ITEMS_TYPES: h.ClassVar[h.Any | tuple[h.Any, ...]] = h.Any
48
+ ANY_LENGTH: h.ClassVar[tuple[int, ...]] = (0,)
49
+
50
+ ACCEPTED_TYPES: h.ClassVar[tuple[type, ...]] = (list, set, tuple)
51
+ items_types: any_hint_h | tuple[any_hint_h, ...] | type_t | tuple[type_t, ...] = (
52
+ ANY_ITEMS_TYPES
53
+ )
54
+ lengths: int | tuple[int, ...] = ANY_LENGTH
55
+
56
+ def __post_init__(self) -> None:
57
+ """"""
58
+ original_item_types = self.items_types
59
+ original_lengths = self.lengths
60
+
61
+ if isinstance(self.items_types, h.Sequence):
62
+ items_types = []
63
+ for stripe in self.items_types:
64
+ if isinstance(stripe, type_t):
65
+ items_types.append(stripe)
66
+ else:
67
+ items_types.append(type_t.NewForHint(stripe))
68
+ self.items_types = items_types
69
+ elif not isinstance(self.items_types, type_t):
70
+ self.items_types = type_t.NewForHint(self.items_types)
71
+
72
+ if isinstance(self.lengths, int):
73
+ self.lengths = (self.lengths,)
74
+ else:
75
+ self.lengths = tuple(sorted(self.lengths))
76
+
77
+ with ISSUE_MANAGER.AddedContextLevel("Collection Annotation"):
78
+ if isinstance(self.items_types, h.Sequence):
79
+ if max(self.lengths) > self.items_types.__len__():
80
+ ISSUE_MANAGER.Add(
81
+ f'Allowed length(s) ("{original_lengths}") must not exceed '
82
+ f"the length of the item types sequence "
83
+ f'("{original_item_types}")'
84
+ )
85
+ if self.lengths != self.__class__.ANY_LENGTH:
86
+ for length in self.lengths:
87
+ if (not isinstance(length, int)) or (length < 0):
88
+ ISSUE_MANAGER.Add(
89
+ f"Invalid length in {self.lengths}",
90
+ actual=length,
91
+ expected="strictly positive integer",
92
+ )
93
+
94
+ @classmethod
95
+ def NewForType(
96
+ cls,
97
+ stripe: any_hint_h | tuple[any_hint_h, ...] | type_t | tuple[type_t, ...],
98
+ /,
99
+ ) -> collection_t:
100
+ """"""
101
+ if not isinstance(stripe, (type_t | tuple[type_t, ...])):
102
+ stripe = type_t.NewForHint(stripe)
103
+
104
+ if stripe.type not in cls.ACCEPTED_TYPES:
105
+ with ISSUE_MANAGER.AddedContextLevel("Collection Annotation"):
106
+ ISSUE_MANAGER.Add(
107
+ f"Invalid type",
108
+ actual=stripe.type.__name__,
109
+ expected=", ".join(_elm.__name__ for _elm in cls.ACCEPTED_TYPES),
110
+ )
111
+ return collection_t()
112
+
113
+ if stripe.elements is None:
114
+ return collection_t()
115
+
116
+ if (n_elements := stripe.elements.__len__()) == 1:
117
+ return collection_t(items_types=stripe.elements[0], lengths=1)
118
+
119
+ if (n_elements == 2) and (stripe.elements[1].type is t.EllipsisType):
120
+ return collection_t(items_types=stripe.elements[0], lengths=cls.ANY_LENGTH)
121
+
122
+ return collection_t(items_types=stripe.elements, lengths=n_elements)
123
+
124
+ def ValueIssues(self, value: list | set | tuple | h.Any, /) -> list[str]:
125
+ """"""
126
+ issues = annotation_t.ValueIssues(self, value)
127
+ if issues.__len__() > 0:
128
+ return issues
129
+
130
+ if (self.lengths != self.__class__.ANY_LENGTH) and (
131
+ value.__len__() not in self.lengths
132
+ ):
133
+ return [
134
+ f"{value}: Sequence of invalid length; "
135
+ f"Expected={' or '.join(map(str, self.lengths))}."
136
+ ]
137
+
138
+ if isinstance(self.items_types, h.Sequence):
139
+ if value.__len__() > self.items_types.__len__():
140
+ return [
141
+ f"{value}: Sequence too long. "
142
+ f"Expected=At most {self.items_types.__len__()} element(s)."
143
+ ]
144
+
145
+ output = []
146
+ for stripe, element in zip(self.items_types, value):
147
+ output.extend(stripe.ValueIssues(element))
148
+ return output
149
+
150
+ stripe: type_t = self.items_types
151
+ output = []
152
+ for element in value:
153
+ output.extend(stripe.ValueIssues(element))
154
+ return output
@@ -0,0 +1,120 @@
1
+ # Copyright CNRS/Inria/UniCA
2
+ # Contributor(s): Eric Debreuve (since 2023)
3
+ #
4
+ # eric.debreuve@cnrs.fr
5
+ #
6
+ # This software is governed by the CeCILL license under French law and
7
+ # abiding by the rules of distribution of free software. You can use,
8
+ # modify and/ or redistribute the software under the terms of the CeCILL
9
+ # license as circulated by CEA, CNRS and INRIA at the following URL
10
+ # "http://www.cecill.info".
11
+ #
12
+ # As a counterpart to the access to the source code and rights to copy,
13
+ # modify and redistribute granted by the license, users are provided only
14
+ # with a limited warranty and the software's author, the holder of the
15
+ # economic rights, and the successive licensors have only limited
16
+ # liability.
17
+ #
18
+ # In this respect, the user's attention is drawn to the risks associated
19
+ # with loading, using, modifying and/or developing or reproducing the
20
+ # software by the user in light of its specific status of free software,
21
+ # that may mean that it is complicated to manipulate, and that also
22
+ # therefore means that it is reserved for developers and experienced
23
+ # professionals having in-depth computer knowledge. Users are therefore
24
+ # encouraged to load and test the software's suitability as regards their
25
+ # requirements in conditions enabling the security of their systems and/or
26
+ # data to be ensured and, more generally, to use and operate it in the
27
+ # same conditions as regards security.
28
+ #
29
+ # The fact that you are presently reading this means that you have had
30
+ # knowledge of the CeCILL license and that you accept its terms.
31
+
32
+ import dataclasses as dtcl
33
+ import typing as h
34
+
35
+ from issue_manager import ISSUE_MANAGER
36
+ from str_to_obj import annotation_t
37
+
38
+ number_h = int | float
39
+
40
+
41
+ @dtcl.dataclass(slots=True, repr=False, eq=False)
42
+ class number_t(annotation_t):
43
+ INFINITY_NEG: h.ClassVar[float] = -float("inf")
44
+ INFINITY_POS: h.ClassVar[float] = float("inf")
45
+ INFINITE_PRECISION: h.ClassVar[float] = 0.0
46
+
47
+ ACCEPTED_TYPES: h.ClassVar[tuple[type, ...]] = (int, float)
48
+ min: number_h = INFINITY_NEG
49
+ max: number_h = INFINITY_POS
50
+ min_inclusive: bool = True
51
+ max_inclusive: bool = True
52
+ precision: number_h = INFINITE_PRECISION
53
+
54
+ def __post_init__(self) -> None:
55
+ """"""
56
+ stripe = self.__class__
57
+
58
+ with ISSUE_MANAGER.AddedContextLevel("Number Annotation"):
59
+ if (self.min != stripe.INFINITY_NEG) and not isinstance(
60
+ self.min, number_h.__args__
61
+ ):
62
+ ISSUE_MANAGER.Add(
63
+ f"Invalid type for min value {self.min}",
64
+ actual=type(self.min).__name__,
65
+ expected=number_h,
66
+ )
67
+ if (self.max != stripe.INFINITY_POS) and not isinstance(
68
+ self.max, number_h.__args__
69
+ ):
70
+ ISSUE_MANAGER.Add(
71
+ f"Invalid type for max value {self.max}",
72
+ actual=type(self.max).__name__,
73
+ expected=number_h,
74
+ )
75
+ if (self.precision != stripe.INFINITE_PRECISION) and not isinstance(
76
+ self.precision, number_h.__args__
77
+ ):
78
+ ISSUE_MANAGER.Add(
79
+ f"Invalid type for precision {self.precision}",
80
+ actual=type(self.precision).__name__,
81
+ expected=number_h,
82
+ )
83
+ if self.precision < 0:
84
+ ISSUE_MANAGER.Add(f"Invalid, negative precision {self.precision}")
85
+ if (self.min > self.max) or (
86
+ (self.min == self.max)
87
+ and not (self.min_inclusive and self.max_inclusive)
88
+ ):
89
+ if self.min_inclusive:
90
+ opening = "["
91
+ else:
92
+ opening = "]"
93
+ if self.max_inclusive:
94
+ closing = "]"
95
+ else:
96
+ closing = "["
97
+ ISSUE_MANAGER.Add(
98
+ f"Empty value interval {opening}{self.min},{self.max}{closing}"
99
+ )
100
+
101
+ def ValueIssues(self, value: number_h, /) -> list[str]:
102
+ """"""
103
+ issues = annotation_t.ValueIssues(self, value)
104
+ if issues.__len__() > 0:
105
+ return issues
106
+
107
+ if self.min <= value <= self.max:
108
+ if ((value == self.min) and not self.min_inclusive) or (
109
+ (value == self.max) and not self.max_inclusive
110
+ ):
111
+ return [f"{value}: Value outside prescribed interval."]
112
+
113
+ if (self.precision != self.__class__.INFINITE_PRECISION) and (
114
+ self.precision * int(value / self.precision) != value
115
+ ):
116
+ return [f"{value}: Value of higher precision than the prescribed one."]
117
+
118
+ return []
119
+ else:
120
+ return [f"{value}: Value outside prescribed interval."]
@@ -0,0 +1,94 @@
1
+ # Copyright CNRS/Inria/UniCA
2
+ # Contributor(s): Eric Debreuve (since 2023)
3
+ #
4
+ # eric.debreuve@cnrs.fr
5
+ #
6
+ # This software is governed by the CeCILL license under French law and
7
+ # abiding by the rules of distribution of free software. You can use,
8
+ # modify and/ or redistribute the software under the terms of the CeCILL
9
+ # license as circulated by CEA, CNRS and INRIA at the following URL
10
+ # "http://www.cecill.info".
11
+ #
12
+ # As a counterpart to the access to the source code and rights to copy,
13
+ # modify and redistribute granted by the license, users are provided only
14
+ # with a limited warranty and the software's author, the holder of the
15
+ # economic rights, and the successive licensors have only limited
16
+ # liability.
17
+ #
18
+ # In this respect, the user's attention is drawn to the risks associated
19
+ # with loading, using, modifying and/or developing or reproducing the
20
+ # software by the user in light of its specific status of free software,
21
+ # that may mean that it is complicated to manipulate, and that also
22
+ # therefore means that it is reserved for developers and experienced
23
+ # professionals having in-depth computer knowledge. Users are therefore
24
+ # encouraged to load and test the software's suitability as regards their
25
+ # requirements in conditions enabling the security of their systems and/or
26
+ # data to be ensured and, more generally, to use and operate it in the
27
+ # same conditions as regards security.
28
+ #
29
+ # The fact that you are presently reading this means that you have had
30
+ # knowledge of the CeCILL license and that you accept its terms.
31
+
32
+ import dataclasses as dtcl
33
+ import typing as h
34
+ from enum import Enum as enum_t
35
+ from pathlib import Path as pl_path_t
36
+
37
+ from str_to_obj import annotation_t
38
+ from str_to_obj.type.hint import annotated_hint_t
39
+
40
+
41
+ class path_type_e(enum_t):
42
+ document = 1
43
+ folder = 2
44
+ any = 3
45
+
46
+
47
+ class path_purpose_e(enum_t):
48
+ input = 1
49
+ output = 2
50
+ any = 3
51
+
52
+
53
+ @dtcl.dataclass(slots=True, repr=False, eq=False)
54
+ class path_t(annotation_t):
55
+
56
+ ACCEPTED_TYPES: h.ClassVar[tuple[type, ...]] = (pl_path_t,)
57
+ type_: path_type_e
58
+ purpose: path_purpose_e
59
+
60
+ @classmethod
61
+ def NewAnnotatedType(
62
+ cls, type_: path_type_e, purpose: path_purpose_e, /
63
+ ) -> annotated_hint_t:
64
+ """"""
65
+ return h.Annotated[pl_path_t, cls(type_=type_, purpose=purpose)]
66
+
67
+ def ValueIssues(self, value: pl_path_t | h.Any, /) -> list[str]:
68
+ """
69
+ None: Unspecified path.
70
+ """
71
+ issues = annotation_t.ValueIssues(self, value)
72
+ if issues.__len__() > 0:
73
+ return issues
74
+
75
+ if self.purpose is not path_purpose_e.input:
76
+ return []
77
+
78
+ if value.exists():
79
+ if self.type_ is path_type_e.any:
80
+ if value.is_file() or value.is_dir():
81
+ return []
82
+ else:
83
+ return [f"{value}: Not a valid file or folder."]
84
+
85
+ if (self.type_ is path_type_e.document) and value.is_file():
86
+ return []
87
+
88
+ if (self.type_ is path_type_e.folder) and value.is_dir():
89
+ return []
90
+
91
+ return [
92
+ f"{value}: Non-existent file or folder, or file for folder, "
93
+ f"or folder for file."
94
+ ]
@@ -29,10 +29,10 @@
29
29
  # The fact that you are presently reading this means that you have had
30
30
  # knowledge of the CeCILL license and that you accept its terms.
31
31
 
32
- from typing import Any, Sequence
32
+ import typing as h
33
33
 
34
34
 
35
- def TypeAsRichStr(value: Any, /, *, prefix: str = "") -> str:
35
+ def TypeAsRichStr(value: h.Any, /, *, prefix: str = "") -> str:
36
36
  """
37
37
  Richer alternative (however, causes troubles with packages like TensorFlow):
38
38
  Additional parameter: relative_to_home: bool = True
@@ -46,10 +46,10 @@ def TypeAsRichStr(value: Any, /, *, prefix: str = "") -> str:
46
46
  return f"[yellow]{prefix}{type(value).__name__}[/]"
47
47
 
48
48
 
49
- def NameValueTypeAsRichStr(name: str, value: Any, /, *, separator: str = "=") -> str:
49
+ def NameValueTypeAsRichStr(name: str, value: h.Any, /, *, separator: str = "=") -> str:
50
50
  """"""
51
51
  formatted_type = TypeAsRichStr(value, prefix=":")
52
- if isinstance(value, Sequence) and (value.__len__() == 0):
52
+ if isinstance(value, h.Sequence) and (value.__len__() == 0):
53
53
  value = "[cyan]<empty>[/]"
54
54
 
55
55
  return f"[blue]{name}[/]{separator}{value}{formatted_type}"
str_to_obj/main.py CHANGED
@@ -30,8 +30,8 @@
30
30
  # knowledge of the CeCILL license and that you accept its terms.
31
31
 
32
32
  import ast as bstr
33
- from types import NoneType
34
- from typing import Any
33
+ import types as t
34
+ import typing as h
35
35
 
36
36
  from str_to_obj.task.casting import CastValue
37
37
  from str_to_obj.type.hint_tree import any_hint_h, hint_tree_t
@@ -41,13 +41,13 @@ def ObjectFromStr(
41
41
  string: str,
42
42
  /,
43
43
  *,
44
- expected_type: any_hint_h | hint_tree_t | type[NoneType] = None,
45
- ) -> tuple[Any, list[str]]:
44
+ expected_type: any_hint_h | hint_tree_t | type[t.NoneType] = None,
45
+ ) -> tuple[h.Any, list[str]]:
46
46
  """
47
47
  expected_type: Must not be passed explicitly as None since None is interpreted as
48
48
  "no specific expected type". When expecting None, pass NoneType.
49
49
  """
50
- if expected_type is NoneType:
50
+ if expected_type is t.NoneType:
51
51
  if string.lower() == "none":
52
52
  issues = []
53
53
  else:
@@ -0,0 +1,36 @@
1
+ # Copyright CNRS/Inria/UNS
2
+ # Contributor(s): Eric Debreuve (since 2023)
3
+ #
4
+ # eric.debreuve@cnrs.fr
5
+ #
6
+ # This software is governed by the CeCILL license under French law and
7
+ # abiding by the rules of distribution of free software. You can use,
8
+ # modify and/ or redistribute the software under the terms of the CeCILL
9
+ # license as circulated by CEA, CNRS and INRIA at the following URL
10
+ # "http://www.cecill.info".
11
+ #
12
+ # As a counterpart to the access to the source code and rights to copy,
13
+ # modify and redistribute granted by the license, users are provided only
14
+ # with a limited warranty and the software's author, the holder of the
15
+ # economic rights, and the successive licensors have only limited
16
+ # liability.
17
+ #
18
+ # In this respect, the user's attention is drawn to the risks associated
19
+ # with loading, using, modifying and/or developing or reproducing the
20
+ # software by the user in light of its specific status of free software,
21
+ # that may mean that it is complicated to manipulate, and that also
22
+ # therefore means that it is reserved for developers and experienced
23
+ # professionals having in-depth computer knowledge. Users are therefore
24
+ # encouraged to load and test the software's suitability as regards their
25
+ # requirements in conditions enabling the security of their systems and/or
26
+ # data to be ensured and, more generally, to use and operate it in the
27
+ # same conditions as regards security.
28
+ #
29
+ # The fact that you are presently reading this means that you have had
30
+ # knowledge of the CeCILL license and that you accept its terms.
31
+
32
+ import typing as h
33
+
34
+ from str_to_obj.type.type import any_type_t
35
+
36
+ ANY_TYPE = any_type_t.NewForHint(h.Any)
@@ -0,0 +1,34 @@
1
+ # Copyright CNRS/Inria/UNS
2
+ # Contributor(s): Eric Debreuve (since 2023)
3
+ #
4
+ # eric.debreuve@cnrs.fr
5
+ #
6
+ # This software is governed by the CeCILL license under French law and
7
+ # abiding by the rules of distribution of free software. You can use,
8
+ # modify and/ or redistribute the software under the terms of the CeCILL
9
+ # license as circulated by CEA, CNRS and INRIA at the following URL
10
+ # "http://www.cecill.info".
11
+ #
12
+ # As a counterpart to the access to the source code and rights to copy,
13
+ # modify and redistribute granted by the license, users are provided only
14
+ # with a limited warranty and the software's author, the holder of the
15
+ # economic rights, and the successive licensors have only limited
16
+ # liability.
17
+ #
18
+ # In this respect, the user's attention is drawn to the risks associated
19
+ # with loading, using, modifying and/or developing or reproducing the
20
+ # software by the user in light of its specific status of free software,
21
+ # that may mean that it is complicated to manipulate, and that also
22
+ # therefore means that it is reserved for developers and experienced
23
+ # professionals having in-depth computer knowledge. Users are therefore
24
+ # encouraged to load and test the software's suitability as regards their
25
+ # requirements in conditions enabling the security of their systems and/or
26
+ # data to be ensured and, more generally, to use and operate it in the
27
+ # same conditions as regards security.
28
+ #
29
+ # The fact that you are presently reading this means that you have had
30
+ # knowledge of the CeCILL license and that you accept its terms.
31
+
32
+ from str_to_obj.type.value import invalid_value_t
33
+
34
+ INVALID_VALUE = invalid_value_t()
@@ -32,9 +32,9 @@
32
32
  from __future__ import annotations
33
33
 
34
34
  import dataclasses as dtcl
35
+ import types as t
36
+ import typing as h
35
37
  from pathlib import Path as path_t
36
- from types import EllipsisType, NoneType, UnionType
37
- from typing import Any, Iterable
38
38
 
39
39
  from str_to_obj.type.hint import any_hint_h, simple_hint_h
40
40
  from str_to_obj.type.hint_tree import hint_tree_t
@@ -55,7 +55,7 @@ class _value_node_t:
55
55
  """
56
56
 
57
57
  type: simple_hint_h = None
58
- leaf_value: Any | None = _NOT_A_LEAF_NODE
58
+ leaf_value: h.Any | None = _NOT_A_LEAF_NODE
59
59
 
60
60
 
61
61
  @dtcl.dataclass(slots=True, repr=False, eq=False)
@@ -63,15 +63,15 @@ class _value_tree_t(_value_node_t):
63
63
  elements: tuple[_value_tree_t, ...] = None
64
64
 
65
65
  @classmethod
66
- def NewFromValue(cls, value: Any, /) -> _value_tree_t:
66
+ def NewFromValue(cls, value: h.Any, /) -> _value_tree_t:
67
67
  """"""
68
- if isinstance(value, Iterable) and not isinstance(value, str):
68
+ if isinstance(value, h.Iterable) and not isinstance(value, str):
69
69
  elements = tuple(cls.NewFromValue(_elm) for _elm in value)
70
70
  return cls(type=type(value), elements=elements)
71
71
 
72
72
  return cls(leaf_value=value)
73
73
 
74
- def _RebuiltValue(self) -> Any:
74
+ def _RebuiltValue(self) -> h.Any:
75
75
  """"""
76
76
  if self.leaf_value is _NOT_A_LEAF_NODE:
77
77
  return self.type(_elm._RebuiltValue() for _elm in self.elements)
@@ -80,7 +80,7 @@ class _value_tree_t(_value_node_t):
80
80
 
81
81
  def CastValue(
82
82
  self, hint_tree: hint_tree_t, /, *, only_check_validity: bool = False
83
- ) -> tuple[Any, list[str]] | list[str]:
83
+ ) -> tuple[h.Any, list[str]] | list[str]:
84
84
  """"""
85
85
  issues = self._CastToHint(hint_tree)
86
86
  if issues.__len__() > 0:
@@ -102,10 +102,10 @@ class _value_tree_t(_value_node_t):
102
102
  hn_type = hint_node.type
103
103
  hn_elements = hint_node.elements
104
104
 
105
- if hn_type is Any:
105
+ if hn_type is h.Any:
106
106
  return self._CompliesWithAnnotations(hint_node)
107
107
 
108
- if hn_type is NoneType:
108
+ if hn_type is t.NoneType:
109
109
  # None is not supposed to have annotations. They are ignored if it does.
110
110
  if self.leaf_value is None:
111
111
  output = []
@@ -113,7 +113,7 @@ class _value_tree_t(_value_node_t):
113
113
  output = [f"{self.leaf_value}: Invalid value; Expected=None."]
114
114
  return output
115
115
 
116
- if hn_type is UnionType:
116
+ if hn_type is t.UnionType:
117
117
  issues = []
118
118
  for element in hn_elements:
119
119
  local_issues = self._CastToHint(element)
@@ -167,8 +167,11 @@ class _value_tree_t(_value_node_t):
167
167
  rebuilt = self._RebuiltValue()
168
168
  try:
169
169
  _ = hn_type(rebuilt)
170
- except:
171
- return [f"{rebuilt}: Cannot be cast to type {hn_type.__name__}."]
170
+ except Exception as exception:
171
+ return [
172
+ f"{rebuilt}: Cannot be cast to type {hn_type.__name__} "
173
+ f"({exception.__class__.__name__})."
174
+ ]
172
175
  else:
173
176
  self.type = hn_type
174
177
 
@@ -176,7 +179,9 @@ class _value_tree_t(_value_node_t):
176
179
 
177
180
  n_value_elements = self.elements.__len__()
178
181
  n_hint_elements = hn_elements.__len__()
179
- has_ellipsis = (n_hint_elements == 2) and (hn_elements[1].type is EllipsisType)
182
+ has_ellipsis = (n_hint_elements == 2) and (
183
+ hn_elements[1].type is t.EllipsisType
184
+ )
180
185
  should_fake_ellipsis = (n_hint_elements == 1) and issubclass(
181
186
  hn_type, (list, set)
182
187
  )
@@ -208,17 +213,21 @@ class _value_tree_t(_value_node_t):
208
213
  output = []
209
214
 
210
215
  for annotation in hint_node.annotations:
211
- output.extend(annotation.ValueIsCompliant(self._RebuiltValue()))
216
+ output.extend(annotation.ValueIssues(self._RebuiltValue()))
212
217
 
213
218
  return output
214
219
 
215
220
 
216
221
  def CastValue(
217
- value: Any, hint: any_hint_h | hint_tree_t, /, *, only_check_validity: bool = False
218
- ) -> tuple[Any, list[str]] | list[str]:
222
+ value: h.Any,
223
+ hint: any_hint_h | hint_tree_t,
224
+ /,
225
+ *,
226
+ only_check_validity: bool = False,
227
+ ) -> tuple[h.Any, list[str]] | list[str]:
219
228
  """"""
220
229
  value_tree = _value_tree_t.NewFromValue(value)
221
230
  if not isinstance(hint, hint_tree_t):
222
- hint = hint_tree_t.NewFromTypeHint(hint)
231
+ hint = hint_tree_t.NewForHint(hint)
223
232
 
224
233
  return value_tree.CastValue(hint, only_check_validity=only_check_validity)
@@ -29,8 +29,8 @@
29
29
  # The fact that you are presently reading this means that you have had
30
30
  # knowledge of the CeCILL license and that you accept its terms.
31
31
 
32
+ import types as t
32
33
  import typing as h
33
- from types import UnionType
34
34
 
35
35
  from str_to_obj.type.hint_tree import hint_tree_t
36
36
 
@@ -47,12 +47,12 @@ def TypesAreCompatible(
47
47
  if h.Any in (one.type, another.type):
48
48
  return True
49
49
 
50
- if one.type is UnionType:
50
+ if one.type is t.UnionType:
51
51
  return any(
52
52
  TypesAreCompatible(_elm, another, strict_mode=strict_mode)
53
53
  for _elm in one.elements
54
54
  )
55
- if another.type is UnionType:
55
+ if another.type is t.UnionType:
56
56
  return any(
57
57
  TypesAreCompatible(one, _elm, strict_mode=strict_mode)
58
58
  for _elm in another.elements
@@ -29,7 +29,7 @@
29
29
  # The fact that you are presently reading this means that you have had
30
30
  # knowledge of the CeCILL license and that you accept its terms.
31
31
 
32
- from typing import Any
32
+ import typing as h
33
33
 
34
34
  from str_to_obj.type.annotation import annotation_t
35
35
  from str_to_obj.type.hint import annotated_hint_t, any_hint_h, raw_hint_h
@@ -45,7 +45,9 @@ def TypeOfAnnotatedHint(annotated_hint: annotated_hint_t, /) -> raw_hint_h:
45
45
  return annotated_hint.__args__[0]
46
46
 
47
47
 
48
- def AnnotationsOfAnnotatedHint(annotated_hint: annotated_hint_t, /) -> tuple[Any, ...]:
48
+ def AnnotationsOfAnnotatedHint(
49
+ annotated_hint: annotated_hint_t, /
50
+ ) -> tuple[h.Any, ...]:
49
51
  """"""
50
52
  output = tuple(annotated_hint.__metadata__)
51
53
  if all(isinstance(_elm, annotation_t) for _elm in output):
@@ -56,7 +58,7 @@ def AnnotationsOfAnnotatedHint(annotated_hint: annotated_hint_t, /) -> tuple[Any
56
58
  )
57
59
 
58
60
 
59
- def HintComponents(hint: any_hint_h, /) -> tuple[raw_hint_h, tuple[Any, ...]]:
61
+ def HintComponents(hint: any_hint_h, /) -> tuple[raw_hint_h, tuple[h.Any, ...]]:
60
62
  """"""
61
63
  if IsAnnotated(hint):
62
64
  return TypeOfAnnotatedHint(hint), AnnotationsOfAnnotatedHint(hint)
@@ -30,20 +30,16 @@
30
30
  # knowledge of the CeCILL license and that you accept its terms.
31
31
 
32
32
  import dataclasses as dtcl
33
- from typing import Any, ClassVar
33
+ import typing as h
34
34
 
35
35
  from rich.text import Text as text_t
36
-
37
- from str_to_obj.interface.console import (
38
- NameValueTypeAsRichStr,
39
- TypeAsRichStr,
40
- )
36
+ from str_to_obj.interface.console import NameValueTypeAsRichStr, TypeAsRichStr
41
37
  from str_to_obj.type.hint import annotated_hint_t, non_complex_hint_h
42
38
 
43
39
 
44
40
  @dtcl.dataclass(slots=True, repr=False, eq=False)
45
41
  class annotation_t:
46
- ACCEPTED_TYPES: ClassVar[tuple[non_complex_hint_h, ...]] = (Any,)
42
+ ACCEPTED_TYPES: h.ClassVar[tuple[non_complex_hint_h, ...]] = (h.Any,)
47
43
 
48
44
  @classmethod
49
45
  def NewAnnotatedType(cls, *args, **kwargs) -> annotated_hint_t:
@@ -57,11 +53,11 @@ class annotation_t:
57
53
  """
58
54
  raise NotImplementedError
59
55
 
60
- def ValueIsCompliant(self, value: Any, /) -> list[str]:
56
+ def ValueIssues(self, value: h.Any, /) -> list[str]:
61
57
  """"""
62
58
  types = self.__class__.ACCEPTED_TYPES
63
59
  stripe = type(value)
64
- if (Any in types) or (stripe in types) or issubclass(stripe, types):
60
+ if (h.Any in types) or (stripe in types) or issubclass(stripe, types):
65
61
  return []
66
62
 
67
63
  expected = " or ".join(map(str, types))
str_to_obj/type/hint.py CHANGED
@@ -29,14 +29,14 @@
29
29
  # The fact that you are presently reading this means that you have had
30
30
  # knowledge of the CeCILL license and that you accept its terms.
31
31
 
32
- from types import EllipsisType, GenericAlias, UnionType
33
- from typing import Annotated, Any
32
+ import types as t
33
+ import typing as h
34
34
 
35
35
  # --- Unannotated hints
36
36
  # Atoms
37
- generic_hint_h = Any
38
- simple_hint_h = type[Any]
39
- complex_hint_h = GenericAlias | UnionType
37
+ generic_hint_h = h.Any
38
+ simple_hint_h = type[h.Any]
39
+ complex_hint_h = t.GenericAlias | t.UnionType
40
40
 
41
41
  # Grouping
42
42
  non_complex_hint_h = generic_hint_h | simple_hint_h
@@ -44,7 +44,7 @@ raw_hint_h = non_complex_hint_h | complex_hint_h
44
44
 
45
45
 
46
46
  # --- Annotated hints
47
- annotated_hint_t = type(Annotated[object, None])
47
+ annotated_hint_t = type(h.Annotated[object, None])
48
48
 
49
49
 
50
50
  # --- [Un]Annotated hints
@@ -54,4 +54,4 @@ any_hint_h = raw_hint_h | annotated_hint_t
54
54
  # --- Complex hints additional components:
55
55
  # - EllipsisType for GenericAlias, as in: tuple[int, ...]
56
56
  # - None for UnionType, as in: int | None
57
- complex_hint_additions_h = EllipsisType | None
57
+ complex_hint_additions_h = t.EllipsisType | None
@@ -33,8 +33,8 @@ from __future__ import annotations
33
33
 
34
34
  import dataclasses as dtcl
35
35
  import re as regx
36
- from types import EllipsisType, NoneType, UnionType
37
- from typing import Any, Union, get_args, get_origin
36
+ import types as t
37
+ import typing as h
38
38
 
39
39
  from str_to_obj.task.inspection import HintComponents
40
40
  from str_to_obj.type.annotation import annotation_t
@@ -52,7 +52,7 @@ class _hint_node_t:
52
52
  Leave elements to the tree.
53
53
  """
54
54
 
55
- type: non_complex_hint_h | UnionType | EllipsisType | type[NoneType]
55
+ type: non_complex_hint_h | t.UnionType | t.EllipsisType | type[t.NoneType]
56
56
  annotations: tuple[annotation_t, ...] = dtcl.field(default_factory=tuple)
57
57
 
58
58
 
@@ -61,9 +61,7 @@ class hint_tree_t(_hint_node_t):
61
61
  elements: tuple[hint_tree_t, ...] = None
62
62
 
63
63
  @classmethod
64
- def NewFromTypeHint(
65
- cls, hint: any_hint_h | complex_hint_additions_h, /
66
- ) -> hint_tree_t:
64
+ def NewForHint(cls, hint: any_hint_h | complex_hint_additions_h, /) -> hint_tree_t:
67
65
  """
68
66
  Note that type hints cannot translate into hint trees with an OR-node having a child
69
67
  OR-node. For example: str | (int | float) is interpreted as str | int | float. This
@@ -80,24 +78,24 @@ class hint_tree_t(_hint_node_t):
80
78
 
81
79
  # Dealing with complex_hint_additions_h first
82
80
  if hint is Ellipsis:
83
- return cls(type=EllipsisType)
84
- if (hint is None) or (hint is NoneType):
85
- return cls(type=NoneType)
81
+ return cls(type=t.EllipsisType)
82
+ if (hint is None) or (hint is t.NoneType):
83
+ return cls(type=t.NoneType)
86
84
 
87
85
  # nnts: Do not use "annotations" since it shadows __future__.annotations.
88
86
  raw_hint, nnts = HintComponents(hint)
89
87
 
90
- if (origin := get_origin(raw_hint)) is None:
88
+ if (origin := h.get_origin(raw_hint)) is None:
91
89
  return cls(type=raw_hint, annotations=nnts)
92
90
 
93
91
  # Handled types: list, set, tuple, with sets using the dict delimiters { and }.
94
92
  if origin is dict:
95
93
  raise TypeError(f"{origin.__name__}: Unhandled type.")
96
94
 
97
- if origin is Union:
98
- origin = UnionType
95
+ if origin is h.Union:
96
+ origin = t.UnionType
99
97
  # get_args returns NoneType for None. This must be taken into account above.
100
- elements = tuple(cls.NewFromTypeHint(_elm) for _elm in get_args(raw_hint))
98
+ elements = tuple(cls.NewForHint(_elm) for _elm in h.get_args(raw_hint))
101
99
  return cls(type=origin, annotations=nnts, elements=elements)
102
100
 
103
101
  @property
@@ -112,12 +110,12 @@ class hint_tree_t(_hint_node_t):
112
110
  return output
113
111
 
114
112
  @property
115
- def template(self) -> simple_hint_h | dict[int, Any] | None:
113
+ def template(self) -> simple_hint_h | dict[int, h.Any] | None:
116
114
  """"""
117
- if self.type is NoneType:
115
+ if self.type is t.NoneType:
118
116
  return None
119
117
 
120
- if self.type is UnionType:
118
+ if self.type is t.UnionType:
121
119
  return {_key: _elm.template for _key, _elm in enumerate(self.elements)}
122
120
 
123
121
  if self.elements is None:
@@ -143,12 +141,12 @@ class hint_tree_t(_hint_node_t):
143
141
  """"""
144
142
  output = (
145
143
  str(self.template)
146
- .replace(str(EllipsisType), "...")
144
+ .replace(str(t.EllipsisType), "...")
147
145
  .replace("<class '", "")
148
146
  .replace("'>", "")
149
147
  )
150
- output = regx.sub("{\d: ", "{", output, flags=regx.ASCII)
151
- output = regx.sub(", \d:", " |", output, flags=regx.ASCII)
148
+ output = regx.sub(r"{\d: ", "{", output, flags=regx.ASCII)
149
+ output = regx.sub(r", \d:", " |", output, flags=regx.ASCII)
152
150
 
153
151
  return output
154
152
 
@@ -0,0 +1,97 @@
1
+ # Copyright CNRS/Inria/UniCA
2
+ # Contributor(s): Eric Debreuve (since 2021)
3
+ #
4
+ # eric.debreuve@cnrs.fr
5
+ #
6
+ # This software is governed by the CeCILL license under French law and
7
+ # abiding by the rules of distribution of free software. You can use,
8
+ # modify and/ or redistribute the software under the terms of the CeCILL
9
+ # license as circulated by CEA, CNRS and INRIA at the following URL
10
+ # "http://www.cecill.info".
11
+ #
12
+ # As a counterpart to the access to the source code and rights to copy,
13
+ # modify and redistribute granted by the license, users are provided only
14
+ # with a limited warranty and the software's author, the holder of the
15
+ # economic rights, and the successive licensors have only limited
16
+ # liability.
17
+ #
18
+ # In this respect, the user's attention is drawn to the risks associated
19
+ # with loading, using, modifying and/or developing or reproducing the
20
+ # software by the user in light of its specific status of free software,
21
+ # that may mean that it is complicated to manipulate, and that also
22
+ # therefore means that it is reserved for developers and experienced
23
+ # professionals having in-depth computer knowledge. Users are therefore
24
+ # encouraged to load and test the software's suitability as regards their
25
+ # requirements in conditions enabling the security of their systems and/or
26
+ # data to be ensured and, more generally, to use and operate it in the
27
+ # same conditions as regards security.
28
+ #
29
+ # The fact that you are presently reading this means that you have had
30
+ # knowledge of the CeCILL license and that you accept its terms.
31
+
32
+ import dataclasses as dtcl
33
+ import typing as h
34
+
35
+ from rich.text import Text as text_t
36
+ from str_to_obj import CastValue, ObjectFromStr, annotation_t
37
+ from str_to_obj.runtime.value import INVALID_VALUE
38
+ from str_to_obj.type.hint_tree import hint_tree_t
39
+
40
+
41
+ @dtcl.dataclass(slots=True, repr=False, eq=False)
42
+ class type_t(hint_tree_t):
43
+ def FirstAnnotationWithType(
44
+ self, stripe: type[annotation_t], /
45
+ ) -> annotation_t | None:
46
+ """"""
47
+ for annotation in self.all_annotations:
48
+ if isinstance(annotation, stripe):
49
+ return annotation
50
+
51
+ return None
52
+
53
+ def ValueIssues(self, value: h.Any, /) -> list[str]:
54
+ """"""
55
+ return CastValue(value, self, only_check_validity=True)
56
+
57
+ def InterpretedValueOf(self, value: h.Any, /) -> tuple[h.Any, list[str]]:
58
+ """"""
59
+ if isinstance(value, str):
60
+ typed_value, issues = ObjectFromStr(value, expected_type=self)
61
+ else:
62
+ typed_value, issues = CastValue(value, self)
63
+
64
+ if issues.__len__() > 0:
65
+ return INVALID_VALUE, issues
66
+
67
+ return typed_value, []
68
+
69
+ def __str__(self) -> str:
70
+ """"""
71
+ return text_t.from_markup(self.__rich__()).plain
72
+
73
+ def __rich__(self) -> str:
74
+ """"""
75
+ output = [f"[white]{self.template_as_str}[/]"]
76
+
77
+ for annotation in self.all_annotations:
78
+ output.append(type(annotation).__name__)
79
+
80
+ return "[yellow]" + "::".join(output) + "[/]"
81
+
82
+
83
+ @dtcl.dataclass(slots=True, repr=False, eq=False)
84
+ class any_type_t(type_t):
85
+ def FirstAnnotationWithType(
86
+ self, stripe: type[annotation_t], /
87
+ ) -> annotation_t | None:
88
+ """"""
89
+ return None
90
+
91
+ def ValueIssues(self, _: h.Any, /) -> list[str]:
92
+ """"""
93
+ return []
94
+
95
+ def InterpretedValueOf(self, value: h.Any, /) -> tuple[h.Any, list[str]]:
96
+ """"""
97
+ return value, []
@@ -0,0 +1,47 @@
1
+ # Copyright CNRS/Inria/UniCA
2
+ # Contributor(s): Eric Debreuve (since 2021)
3
+ #
4
+ # eric.debreuve@cnrs.fr
5
+ #
6
+ # This software is governed by the CeCILL license under French law and
7
+ # abiding by the rules of distribution of free software. You can use,
8
+ # modify and/ or redistribute the software under the terms of the CeCILL
9
+ # license as circulated by CEA, CNRS and INRIA at the following URL
10
+ # "http://www.cecill.info".
11
+ #
12
+ # As a counterpart to the access to the source code and rights to copy,
13
+ # modify and redistribute granted by the license, users are provided only
14
+ # with a limited warranty and the software's author, the holder of the
15
+ # economic rights, and the successive licensors have only limited
16
+ # liability.
17
+ #
18
+ # In this respect, the user's attention is drawn to the risks associated
19
+ # with loading, using, modifying and/or developing or reproducing the
20
+ # software by the user in light of its specific status of free software,
21
+ # that may mean that it is complicated to manipulate, and that also
22
+ # therefore means that it is reserved for developers and experienced
23
+ # professionals having in-depth computer knowledge. Users are therefore
24
+ # encouraged to load and test the software's suitability as regards their
25
+ # requirements in conditions enabling the security of their systems and/or
26
+ # data to be ensured and, more generally, to use and operate it in the
27
+ # same conditions as regards security.
28
+ #
29
+ # The fact that you are presently reading this means that you have had
30
+ # knowledge of the CeCILL license and that you accept its terms.
31
+
32
+
33
+ class invalid_value_t:
34
+ """
35
+ Do not use invalid_value_t = object, for example, otherwise isinstance returns True
36
+ for anything.
37
+ """
38
+
39
+ TEXT = "INVALID VALUE"
40
+
41
+ def __str__(self) -> str:
42
+ """"""
43
+ return self.__class__.TEXT
44
+
45
+ def __rich__(self) -> str:
46
+ """"""
47
+ return f"[red]{self.__class__.TEXT}[/]"
str_to_obj/version.py CHANGED
@@ -29,6 +29,6 @@
29
29
  # The fact that you are presently reading this means that you have had
30
30
  # knowledge of the CeCILL license and that you accept its terms.
31
31
 
32
- __version__ = "2024.1"
32
+ __version__ = "2024.2"
33
33
 
34
34
  # TODO: Switch to issue-manager.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: str-to-obj
3
- Version: 2024.1
3
+ Version: 2024.2
4
4
  Summary: Convert strings to Python objects guided by (potentially annotated) type hints
5
5
  Home-page: https://src.koda.cnrs.fr/eric.debreuve/str-to-obj/
6
6
  Author: Eric Debreuve
@@ -0,0 +1,24 @@
1
+ str_to_obj/__init__.py,sha256=odgBU079fpQMu9GXhY0Lc19Rris-8Oa60Dd4F5SxGpQ,1735
2
+ str_to_obj/main.py,sha256=ZcH2KpO9AO6Ozoroin_KkY78P5kV625sALf-ffbIOkE,2481
3
+ str_to_obj/version.py,sha256=d_xwIXU-KduqN957zZV4jgOF0cvsoXCMoiHAWH2TF68,1609
4
+ str_to_obj/catalog/boolean.py,sha256=-1k39odWGgm42cotKxdV00i_M4UbKByK_V8gawgYmjY,2724
5
+ str_to_obj/catalog/callable.py,sha256=mYj-qNGY0ncvFBNzzbphb0hOF1YMqPaXX1iRr6rev1c,2985
6
+ str_to_obj/catalog/choices.py,sha256=CxBngQYiC7Pct-sLQHmtDaPr93gt_H_DreO9-s3Znv0,3176
7
+ str_to_obj/catalog/collection.py,sha256=rOUtBkfL6KV05HtkHaMOrTls0bXRIq1lCECLvN_B37Q,6193
8
+ str_to_obj/catalog/number.py,sha256=UmUkOwnwNZyNxDeXzm_rZHFHpnzc5ovg3Us47Uord5c,4840
9
+ str_to_obj/catalog/path.py,sha256=rri5nZbZClINC__VzS4a6CpRvaLvkSVqcattuWGP9Ys,3217
10
+ str_to_obj/interface/console.py,sha256=YF95b31qPqzeG4lnYtoJ7awQM3QDSOhIjZUeadGd7L4,2406
11
+ str_to_obj/runtime/type.py,sha256=diT38JyuZHJb5-uzIf97s9iDzp_ADyLto5LGg0H3tyc,1657
12
+ str_to_obj/runtime/value.py,sha256=cj7RvdAEy9Xc6INaGGq0CirjZ9gv-moFFUlXuFbzvP8,1637
13
+ str_to_obj/task/casting.py,sha256=0CEVkXXLR9-8ilL3IbnrTTWx-q8Wvkx1VLPVEuCXgx8,8601
14
+ str_to_obj/task/comparison.py,sha256=j6YHHRrkR2oucQnwshl0fMQm7ReuaJFVpwqMHgld5X0,2562
15
+ str_to_obj/task/inspection.py,sha256=9wllLu9WmkB3LfduBnT4Wa47M4UzGy5bJK9OTnPfOgI,2494
16
+ str_to_obj/type/annotation.py,sha256=dmLMtOnbP4NP7pPYEy9r7YhHF21EoTyz2BaO4vkB7qk,3216
17
+ str_to_obj/type/hint.py,sha256=jlQgGosqoszkreJYFS_pga5RpqrUiLYALoxtzrB5rPU,2180
18
+ str_to_obj/type/hint_tree.py,sha256=-24_WCPX94K5ryY6DZKV-_4vnTyaqPV3vJ-OVX-iuxQ,6052
19
+ str_to_obj/type/type.py,sha256=6KZgHRKZi1zzJ9KiW2LLvUXVr0EALUM4Yz8cwvgFeBg,3459
20
+ str_to_obj/type/value.py,sha256=9sXtYf0kVHVpcczS_ZtVZa9_M17pIlYSZjYYE33sS1Y,1904
21
+ str_to_obj-2024.2.dist-info/METADATA,sha256=ujALfzQppSFkyY2oPL2AdazmE1TvWHGpNVbkR6zCVhk,5389
22
+ str_to_obj-2024.2.dist-info/WHEEL,sha256=cpQTJ5IWu9CdaPViMhC9YzF8gZuS5-vlfoFihTBC86A,91
23
+ str_to_obj-2024.2.dist-info/top_level.txt,sha256=h-6bR_TAnXRGVSLTeNPlivlaG64xYM3E__Xg7sCgeug,11
24
+ str_to_obj-2024.2.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.43.0)
2
+ Generator: setuptools (70.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,14 +0,0 @@
1
- str_to_obj/__init__.py,sha256=odgBU079fpQMu9GXhY0Lc19Rris-8Oa60Dd4F5SxGpQ,1735
2
- str_to_obj/main.py,sha256=YxjO1kyeZxGf_31KRZVZ39F7gr0gYM1OyOa7Y8m4iG8,2488
3
- str_to_obj/version.py,sha256=rlojaXevssZP7Crmyq2gSWwZ5xM-WJW9n3iVSVFSO18,1609
4
- str_to_obj/interface/console.py,sha256=PHcDGFmscXYSrPOJRjmlBPglQUBBGUhe1Bov3pthGT0,2414
5
- str_to_obj/task/casting.py,sha256=74eIRKpokqq-JqEK0UwRSQs1F4Zdj8pRDQXAPkqg3Ug,8468
6
- str_to_obj/task/comparison.py,sha256=-1xreDu25SrWyTEGwcZMctURj2A47zAh2QJdMf4EuTg,2568
7
- str_to_obj/task/inspection.py,sha256=dwaK4uMN5iPgcWWVnFu86eSkuPy1G_phBAGTqEa_414,2488
8
- str_to_obj/type/annotation.py,sha256=bR7tQVfYmAohizn4APx_D0aNoPo6gMjyFRoa-QpDNKM,3241
9
- str_to_obj/type/hint.py,sha256=Jv3m1VbXICsUwPTCFidW6A1bX-xgNU2twRP_H1DX5v4,2221
10
- str_to_obj/type/hint_tree.py,sha256=1Gp4I6kgRGshKQJBurJF0wbG02xv-d5Spe2f-4h19qk,6113
11
- str_to_obj-2024.1.dist-info/METADATA,sha256=_AkIgj6_TGFJvuo0wvmP5Hdnuk9Z8jtbxbo_OaqmuQU,5389
12
- str_to_obj-2024.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
13
- str_to_obj-2024.1.dist-info/top_level.txt,sha256=h-6bR_TAnXRGVSLTeNPlivlaG64xYM3E__Xg7sCgeug,11
14
- str_to_obj-2024.1.dist-info/RECORD,,