pyglove 0.4.5.dev20240319__py3-none-any.whl → 0.4.5.dev202501132210__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.
- pyglove/core/__init__.py +54 -20
- pyglove/core/coding/__init__.py +42 -0
- pyglove/core/coding/errors.py +111 -0
- pyglove/core/coding/errors_test.py +98 -0
- pyglove/core/coding/execution.py +309 -0
- pyglove/core/coding/execution_test.py +333 -0
- pyglove/core/{object_utils/codegen.py → coding/function_generation.py} +10 -4
- pyglove/core/{object_utils/codegen_test.py → coding/function_generation_test.py} +5 -7
- pyglove/core/coding/parsing.py +153 -0
- pyglove/core/coding/parsing_test.py +150 -0
- pyglove/core/coding/permissions.py +100 -0
- pyglove/core/coding/permissions_test.py +93 -0
- pyglove/core/geno/base.py +54 -41
- pyglove/core/geno/base_test.py +2 -4
- pyglove/core/geno/categorical.py +37 -28
- pyglove/core/geno/custom.py +19 -16
- pyglove/core/geno/numerical.py +20 -17
- pyglove/core/geno/space.py +4 -5
- pyglove/core/hyper/base.py +6 -6
- pyglove/core/hyper/categorical.py +94 -55
- pyglove/core/hyper/custom.py +7 -7
- pyglove/core/hyper/custom_test.py +9 -10
- pyglove/core/hyper/derived.py +30 -22
- pyglove/core/hyper/derived_test.py +2 -4
- pyglove/core/hyper/dynamic_evaluation.py +5 -6
- pyglove/core/hyper/evolvable.py +57 -46
- pyglove/core/hyper/numerical.py +48 -24
- pyglove/core/hyper/numerical_test.py +9 -9
- pyglove/core/hyper/object_template.py +58 -46
- pyglove/core/io/__init__.py +1 -0
- pyglove/core/io/file_system.py +17 -7
- pyglove/core/io/file_system_test.py +2 -0
- pyglove/core/io/sequence.py +299 -0
- pyglove/core/io/sequence_test.py +124 -0
- pyglove/core/logging_test.py +0 -2
- pyglove/core/patching/object_factory.py +4 -4
- pyglove/core/patching/pattern_based.py +4 -4
- pyglove/core/patching/rule_based.py +17 -5
- pyglove/core/patching/rule_based_test.py +27 -4
- pyglove/core/symbolic/__init__.py +2 -7
- pyglove/core/symbolic/base.py +320 -183
- pyglove/core/symbolic/base_test.py +123 -19
- pyglove/core/symbolic/boilerplate.py +7 -13
- pyglove/core/symbolic/boilerplate_test.py +25 -23
- pyglove/core/symbolic/class_wrapper.py +48 -45
- pyglove/core/symbolic/class_wrapper_test.py +2 -2
- pyglove/core/symbolic/compounding.py +9 -15
- pyglove/core/symbolic/compounding_test.py +2 -4
- pyglove/core/symbolic/dict.py +154 -110
- pyglove/core/symbolic/dict_test.py +238 -130
- pyglove/core/symbolic/diff.py +199 -10
- pyglove/core/symbolic/diff_test.py +226 -0
- pyglove/core/symbolic/flags.py +1 -1
- pyglove/core/symbolic/functor.py +29 -26
- pyglove/core/symbolic/functor_test.py +102 -50
- pyglove/core/symbolic/inferred.py +2 -2
- pyglove/core/symbolic/list.py +81 -50
- pyglove/core/symbolic/list_test.py +119 -97
- pyglove/core/symbolic/object.py +225 -113
- pyglove/core/symbolic/object_test.py +320 -108
- pyglove/core/symbolic/origin.py +17 -14
- pyglove/core/symbolic/origin_test.py +4 -2
- pyglove/core/symbolic/pure_symbolic.py +4 -3
- pyglove/core/symbolic/ref.py +108 -21
- pyglove/core/symbolic/ref_test.py +93 -0
- pyglove/core/symbolic/symbolize_test.py +10 -2
- pyglove/core/tuning/local_backend.py +2 -2
- pyglove/core/tuning/protocols.py +3 -3
- pyglove/core/tuning/sample_test.py +3 -3
- pyglove/core/typing/__init__.py +14 -5
- pyglove/core/typing/annotation_conversion.py +43 -27
- pyglove/core/typing/annotation_conversion_test.py +23 -0
- pyglove/core/typing/callable_ext.py +241 -3
- pyglove/core/typing/callable_ext_test.py +255 -0
- pyglove/core/typing/callable_signature.py +510 -66
- pyglove/core/typing/callable_signature_test.py +619 -99
- pyglove/core/typing/class_schema.py +229 -154
- pyglove/core/typing/class_schema_test.py +149 -95
- pyglove/core/typing/custom_typing.py +5 -4
- pyglove/core/typing/inspect.py +63 -0
- pyglove/core/typing/inspect_test.py +39 -0
- pyglove/core/typing/key_specs.py +10 -11
- pyglove/core/typing/key_specs_test.py +7 -4
- pyglove/core/typing/type_conversion.py +4 -5
- pyglove/core/typing/type_conversion_test.py +12 -12
- pyglove/core/typing/typed_missing.py +6 -7
- pyglove/core/typing/typed_missing_test.py +7 -8
- pyglove/core/typing/value_specs.py +604 -362
- pyglove/core/typing/value_specs_test.py +328 -90
- pyglove/core/utils/__init__.py +164 -0
- pyglove/core/{object_utils → utils}/common_traits.py +3 -67
- pyglove/core/utils/common_traits_test.py +36 -0
- pyglove/core/{object_utils → utils}/docstr_utils.py +23 -0
- pyglove/core/{object_utils → utils}/docstr_utils_test.py +36 -4
- pyglove/core/{object_utils → utils}/error_utils.py +78 -9
- pyglove/core/{object_utils → utils}/error_utils_test.py +61 -5
- pyglove/core/utils/formatting.py +464 -0
- pyglove/core/utils/formatting_test.py +453 -0
- pyglove/core/{object_utils → utils}/hierarchical.py +23 -25
- pyglove/core/{object_utils → utils}/hierarchical_test.py +3 -5
- pyglove/core/{object_utils → utils}/json_conversion.py +177 -52
- pyglove/core/{object_utils → utils}/json_conversion_test.py +97 -16
- pyglove/core/{object_utils → utils}/missing.py +3 -3
- pyglove/core/{object_utils → utils}/missing_test.py +2 -4
- pyglove/core/utils/text_color.py +128 -0
- pyglove/core/utils/text_color_test.py +94 -0
- pyglove/core/{object_utils → utils}/thread_local_test.py +1 -3
- pyglove/core/utils/timing.py +236 -0
- pyglove/core/utils/timing_test.py +154 -0
- pyglove/core/{object_utils → utils}/value_location.py +275 -6
- pyglove/core/utils/value_location_test.py +707 -0
- pyglove/core/views/__init__.py +32 -0
- pyglove/core/views/base.py +804 -0
- pyglove/core/views/base_test.py +580 -0
- pyglove/core/views/html/__init__.py +27 -0
- pyglove/core/views/html/base.py +547 -0
- pyglove/core/views/html/base_test.py +830 -0
- pyglove/core/views/html/controls/__init__.py +35 -0
- pyglove/core/views/html/controls/base.py +275 -0
- pyglove/core/views/html/controls/label.py +207 -0
- pyglove/core/views/html/controls/label_test.py +157 -0
- pyglove/core/views/html/controls/progress_bar.py +183 -0
- pyglove/core/views/html/controls/progress_bar_test.py +97 -0
- pyglove/core/views/html/controls/tab.py +320 -0
- pyglove/core/views/html/controls/tab_test.py +87 -0
- pyglove/core/views/html/controls/tooltip.py +99 -0
- pyglove/core/views/html/controls/tooltip_test.py +99 -0
- pyglove/core/views/html/tree_view.py +1517 -0
- pyglove/core/views/html/tree_view_test.py +1461 -0
- {pyglove-0.4.5.dev20240319.dist-info → pyglove-0.4.5.dev202501132210.dist-info}/METADATA +18 -4
- pyglove-0.4.5.dev202501132210.dist-info/RECORD +214 -0
- {pyglove-0.4.5.dev20240319.dist-info → pyglove-0.4.5.dev202501132210.dist-info}/WHEEL +1 -1
- pyglove/core/object_utils/__init__.py +0 -154
- pyglove/core/object_utils/common_traits_test.py +0 -82
- pyglove/core/object_utils/formatting.py +0 -234
- pyglove/core/object_utils/formatting_test.py +0 -223
- pyglove/core/object_utils/value_location_test.py +0 -385
- pyglove/core/symbolic/schema_utils.py +0 -327
- pyglove/core/symbolic/schema_utils_test.py +0 -57
- pyglove/core/typing/class_schema_utils.py +0 -202
- pyglove/core/typing/class_schema_utils_test.py +0 -194
- pyglove-0.4.5.dev20240319.dist-info/RECORD +0 -185
- /pyglove/core/{object_utils → utils}/thread_local.py +0 -0
- {pyglove-0.4.5.dev20240319.dist-info → pyglove-0.4.5.dev202501132210.dist-info}/LICENSE +0 -0
- {pyglove-0.4.5.dev20240319.dist-info → pyglove-0.4.5.dev202501132210.dist-info}/top_level.txt +0 -0
@@ -11,18 +11,110 @@
|
|
11
11
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
|
-
"""Tests for pyglove.core.typing.callable_signature."""
|
15
|
-
|
16
14
|
import copy
|
15
|
+
import dataclasses
|
17
16
|
import inspect
|
17
|
+
from typing import List
|
18
18
|
import unittest
|
19
19
|
|
20
|
+
from pyglove.core import utils
|
20
21
|
from pyglove.core.typing import annotation_conversion # pylint: disable=unused-import
|
21
22
|
from pyglove.core.typing import callable_signature
|
22
23
|
from pyglove.core.typing import class_schema
|
23
24
|
from pyglove.core.typing import key_specs as ks
|
24
25
|
from pyglove.core.typing import value_specs as vs
|
25
26
|
|
27
|
+
Argument = callable_signature.Argument
|
28
|
+
Signature = callable_signature.Signature
|
29
|
+
|
30
|
+
|
31
|
+
class ArgumentTest(unittest.TestCase):
|
32
|
+
"""Tests for `Argument` class."""
|
33
|
+
|
34
|
+
def test_kind(self):
|
35
|
+
|
36
|
+
class Foo:
|
37
|
+
def bar(self, x, *args, y, **kwargs):
|
38
|
+
del x, args, y, kwargs
|
39
|
+
|
40
|
+
sig = inspect.signature(Foo.bar)
|
41
|
+
self.assertEqual(
|
42
|
+
Argument.Kind.from_parameter(sig.parameters['self']),
|
43
|
+
Argument.Kind.POSITIONAL_OR_KEYWORD
|
44
|
+
)
|
45
|
+
self.assertEqual(
|
46
|
+
Argument.Kind.from_parameter(sig.parameters['x']),
|
47
|
+
Argument.Kind.POSITIONAL_OR_KEYWORD
|
48
|
+
)
|
49
|
+
self.assertEqual(
|
50
|
+
Argument.Kind.from_parameter(sig.parameters['args']),
|
51
|
+
Argument.Kind.VAR_POSITIONAL
|
52
|
+
)
|
53
|
+
self.assertEqual(
|
54
|
+
Argument.Kind.from_parameter(sig.parameters['y']),
|
55
|
+
Argument.Kind.KEYWORD_ONLY
|
56
|
+
)
|
57
|
+
self.assertEqual(
|
58
|
+
Argument.Kind.from_parameter(sig.parameters['kwargs']),
|
59
|
+
Argument.Kind.VAR_KEYWORD
|
60
|
+
)
|
61
|
+
|
62
|
+
def test_init(self):
|
63
|
+
self.assertEqual(
|
64
|
+
Argument(
|
65
|
+
'x', Argument.Kind.VAR_POSITIONAL, vs.List(vs.Int())).value_spec,
|
66
|
+
vs.List(vs.Int(), default=[])
|
67
|
+
)
|
68
|
+
with self.assertRaisesRegex(
|
69
|
+
TypeError,
|
70
|
+
'Variable positional argument .* should have a value of .*List'
|
71
|
+
):
|
72
|
+
Argument('x', Argument.Kind.VAR_POSITIONAL, vs.Int())
|
73
|
+
|
74
|
+
with self.assertRaisesRegex(
|
75
|
+
TypeError,
|
76
|
+
'Variable keyword argument .* should have a value of .*Dict'
|
77
|
+
):
|
78
|
+
Argument('x', Argument.Kind.VAR_KEYWORD, vs.Int())
|
79
|
+
|
80
|
+
def test_from_parameter(self):
|
81
|
+
|
82
|
+
def bar(x: int, *args, y: str, **kwargs):
|
83
|
+
del x, args, y, kwargs
|
84
|
+
|
85
|
+
sig = inspect.signature(bar)
|
86
|
+
self.assertEqual(
|
87
|
+
Argument.from_parameter(sig.parameters['x'], 'arg x', auto_typing=True),
|
88
|
+
Argument(
|
89
|
+
'x', Argument.Kind.POSITIONAL_OR_KEYWORD, vs.Int(),
|
90
|
+
description='arg x'
|
91
|
+
)
|
92
|
+
)
|
93
|
+
self.assertEqual(
|
94
|
+
Argument.from_parameter(sig.parameters['args'], 'varargs'),
|
95
|
+
Argument(
|
96
|
+
'args',
|
97
|
+
Argument.Kind.VAR_POSITIONAL,
|
98
|
+
vs.List(vs.Any(), default=[]),
|
99
|
+
'varargs'
|
100
|
+
)
|
101
|
+
)
|
102
|
+
self.assertEqual(
|
103
|
+
Argument.from_parameter(sig.parameters['y'], 'arg y', auto_typing=True),
|
104
|
+
Argument(
|
105
|
+
'y', Argument.Kind.KEYWORD_ONLY, vs.Str(), description='arg y'
|
106
|
+
)
|
107
|
+
)
|
108
|
+
self.assertEqual(
|
109
|
+
Argument.from_parameter(sig.parameters['kwargs'], 'kwargs'),
|
110
|
+
Argument(
|
111
|
+
'kwargs',
|
112
|
+
Argument.Kind.VAR_KEYWORD,
|
113
|
+
vs.Dict(vs.Any()),
|
114
|
+
'kwargs'
|
115
|
+
)
|
116
|
+
)
|
117
|
+
|
26
118
|
|
27
119
|
class SignatureTest(unittest.TestCase):
|
28
120
|
"""Tests for `Signature` class."""
|
@@ -30,26 +122,37 @@ class SignatureTest(unittest.TestCase):
|
|
30
122
|
def test_basics(self):
|
31
123
|
"""Test basics of `Signature` class."""
|
32
124
|
|
33
|
-
def foo(a, b: int = 1):
|
125
|
+
def foo(a, *, b: int = 1):
|
34
126
|
del a, b
|
35
127
|
|
36
|
-
signature = callable_signature.
|
128
|
+
signature = callable_signature.signature(
|
129
|
+
foo, auto_typing=False, auto_doc=False
|
130
|
+
)
|
37
131
|
self.assertEqual(signature.module_name, 'pyglove.core.typing.callable_signature_test')
|
38
132
|
self.assertEqual(signature.name, 'foo')
|
39
|
-
self.assertEqual(
|
40
|
-
|
133
|
+
self.assertEqual(
|
134
|
+
signature.id, 'pyglove.core.typing.callable_signature_test.SignatureTest.test_basics.<locals>.foo'
|
135
|
+
)
|
41
136
|
self.assertEqual(
|
42
137
|
str(signature),
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
138
|
+
inspect.cleandoc("""
|
139
|
+
Signature(
|
140
|
+
'pyglove.core.typing.callable_signature_test.SignatureTest.test_basics.<locals>.foo',
|
141
|
+
args=[
|
142
|
+
Argument(name='a', kind=<Kind.POSITIONAL_OR_KEYWORD: 1>, value_spec=Any(), description=None)
|
143
|
+
],
|
144
|
+
kwonlyargs=[
|
145
|
+
Argument(name='b', kind=<Kind.KEYWORD_ONLY: 3>, value_spec=Any(default=1, annotation=<class 'int'>), description=None)
|
146
|
+
]
|
147
|
+
)
|
148
|
+
""")
|
149
|
+
)
|
48
150
|
|
49
151
|
self.assertEqual(signature.named_args, [
|
50
|
-
|
51
|
-
|
52
|
-
'b', vs.Any(default=1).annotate(int)
|
152
|
+
Argument('a', Argument.Kind.POSITIONAL_OR_KEYWORD, vs.Any()),
|
153
|
+
Argument(
|
154
|
+
'b', Argument.Kind.KEYWORD_ONLY, vs.Any(default=1).annotate(int)
|
155
|
+
),
|
53
156
|
])
|
54
157
|
self.assertEqual(signature.arg_names, ['a', 'b'])
|
55
158
|
|
@@ -61,42 +164,249 @@ class SignatureTest(unittest.TestCase):
|
|
61
164
|
|
62
165
|
assert_not_equal(signature, 'name', 'bar')
|
63
166
|
assert_not_equal(signature, 'module_name', 'other_module')
|
64
|
-
assert_not_equal(
|
65
|
-
|
66
|
-
|
167
|
+
assert_not_equal(
|
168
|
+
signature, 'args',
|
169
|
+
[signature.args[0],
|
170
|
+
Argument('b', Argument.Kind.POSITIONAL_OR_KEYWORD, vs.Int())]
|
171
|
+
)
|
67
172
|
assert_not_equal(
|
68
173
|
signature, 'kwonlyargs',
|
69
174
|
list(signature.kwonlyargs) + [
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
175
|
+
Argument('x', Argument.Kind.KEYWORD_ONLY, vs.Any())]
|
176
|
+
)
|
177
|
+
assert_not_equal(
|
178
|
+
signature, 'varargs',
|
179
|
+
Argument('args', Argument.Kind.POSITIONAL_OR_KEYWORD, vs.Any())
|
180
|
+
)
|
181
|
+
assert_not_equal(
|
182
|
+
signature, 'varkw',
|
183
|
+
Argument(
|
184
|
+
'kwargs',
|
185
|
+
Argument.Kind.VAR_KEYWORD,
|
186
|
+
vs.Dict(vs.Any())
|
187
|
+
)
|
188
|
+
)
|
75
189
|
self.assertNotEqual(signature, 1)
|
76
190
|
self.assertEqual(signature, signature)
|
77
191
|
self.assertEqual(signature, copy.deepcopy(signature))
|
78
192
|
|
79
193
|
with self.assertRaisesRegex(TypeError, '.* is not callable'):
|
80
|
-
callable_signature.
|
194
|
+
callable_signature.signature(1)
|
195
|
+
|
196
|
+
def test_annotate(self):
|
197
|
+
def foo(a, *args, b=1, **kwargs):
|
198
|
+
del a, b, args, kwargs
|
199
|
+
return 1
|
200
|
+
|
201
|
+
signature = callable_signature.signature(foo).annotate(
|
202
|
+
dict(
|
203
|
+
a=int,
|
204
|
+
b=(int, 'Field b'),
|
205
|
+
c=(vs.Bool(default=True), 'Field c', dict(meta=1)),
|
206
|
+
args=(List[int], 'Varargs'),
|
207
|
+
kwargs=(str, 'Kwargs'),
|
208
|
+
),
|
209
|
+
return_value=int,
|
210
|
+
)
|
211
|
+
self.assertEqual(signature.args, [
|
212
|
+
Argument('a', Argument.Kind.POSITIONAL_OR_KEYWORD, vs.Int()),
|
213
|
+
])
|
214
|
+
self.assertEqual(signature.kwonlyargs, [
|
215
|
+
Argument(
|
216
|
+
'b', Argument.Kind.KEYWORD_ONLY, vs.Int(default=1), 'Field b'
|
217
|
+
),
|
218
|
+
Argument(
|
219
|
+
'c', Argument.Kind.KEYWORD_ONLY, vs.Bool(default=True), 'Field c'
|
220
|
+
),
|
221
|
+
])
|
222
|
+
self.assertEqual(
|
223
|
+
signature.varargs,
|
224
|
+
Argument(
|
225
|
+
'args',
|
226
|
+
Argument.Kind.VAR_POSITIONAL,
|
227
|
+
vs.List(vs.Int(), default=[]),
|
228
|
+
'Varargs'
|
229
|
+
)
|
230
|
+
)
|
231
|
+
self.assertEqual(
|
232
|
+
signature.varkw,
|
233
|
+
Argument(
|
234
|
+
'kwargs', Argument.Kind.VAR_KEYWORD,
|
235
|
+
vs.Dict(vs.Str()), 'Kwargs'
|
236
|
+
)
|
237
|
+
)
|
238
|
+
self.assertEqual(signature.return_value, vs.Int())
|
239
|
+
|
240
|
+
# Customize the typing of kwargs.
|
241
|
+
signature = callable_signature.signature(foo).annotate({ks.StrKey(): int})
|
242
|
+
|
243
|
+
self.assertEqual(
|
244
|
+
signature.varkw,
|
245
|
+
Argument(
|
246
|
+
'kwargs', Argument.Kind.VAR_KEYWORD,
|
247
|
+
vs.Dict(vs.Int())
|
248
|
+
)
|
249
|
+
)
|
250
|
+
|
251
|
+
# Special handling noneable type specification.
|
252
|
+
signature = callable_signature.signature(
|
253
|
+
foo).annotate({'a': vs.Int().noneable()})
|
254
|
+
|
255
|
+
self.assertEqual(
|
256
|
+
signature.args,
|
257
|
+
[Argument(
|
258
|
+
'a', Argument.Kind.POSITIONAL_OR_KEYWORD,
|
259
|
+
# No default value shall be specified.
|
260
|
+
vs.Int(is_noneable=True),
|
261
|
+
)]
|
262
|
+
)
|
263
|
+
|
264
|
+
# Special handling dict type specification.
|
265
|
+
signature = callable_signature.signature(
|
266
|
+
foo).annotate({'a': vs.Dict([('x', vs.Int())])})
|
267
|
+
|
268
|
+
self.assertEqual(
|
269
|
+
signature.args,
|
270
|
+
[Argument(
|
271
|
+
'a', Argument.Kind.POSITIONAL_OR_KEYWORD,
|
272
|
+
vs.Dict([('x', vs.Int())])
|
273
|
+
)]
|
274
|
+
)
|
275
|
+
|
276
|
+
# Bad override.
|
277
|
+
signature = callable_signature.signature(foo)
|
278
|
+
|
279
|
+
with self.assertRaisesRegex(
|
280
|
+
ValueError, 'return value spec should not have default value'
|
281
|
+
):
|
282
|
+
signature.annotate(return_value=vs.Int(default=1))
|
283
|
+
|
284
|
+
with self.assertRaisesRegex(ValueError, '.*pg.typing.List'):
|
285
|
+
signature.annotate(dict(args=int))
|
286
|
+
|
287
|
+
with self.assertRaisesRegex(KeyError, '.*multiple StrKey'):
|
288
|
+
signature.annotate([(ks.StrKey(), int), ('kwargs', str)])
|
289
|
+
|
290
|
+
with self.assertRaisesRegex(KeyError, '.*multiple StrKey'):
|
291
|
+
signature.annotate([('kwargs', str), (ks.StrKey(), int)])
|
292
|
+
|
293
|
+
with self.assertRaisesRegex(ValueError, 'The annotated default value'):
|
294
|
+
signature.annotate([('b', vs.Int(default=2))])
|
295
|
+
|
296
|
+
with self.assertRaisesRegex(TypeError, 'Expect .* but encountered'):
|
297
|
+
signature.annotate([('b', vs.Str())])
|
298
|
+
|
299
|
+
signature = callable_signature.signature(lambda a: 1)
|
300
|
+
with self.assertRaisesRegex(KeyError, '.*found extra symbolic argument'):
|
301
|
+
signature.annotate([('b', vs.Int())])
|
302
|
+
|
303
|
+
def test_to_schema(self):
|
304
|
+
|
305
|
+
class Foo:
|
306
|
+
def foo(self, a: int, *args, b: str = 'x', **kwargs) -> str:
|
307
|
+
"""Function foo.
|
308
|
+
|
309
|
+
Args:
|
310
|
+
a: An int.
|
311
|
+
*args: Varargs.
|
312
|
+
b: A str.
|
313
|
+
**kwargs: Kwargs.
|
314
|
+
|
315
|
+
Returns:
|
316
|
+
A str.
|
317
|
+
"""
|
318
|
+
del a, args, kwargs
|
319
|
+
return b
|
320
|
+
|
321
|
+
schema = Signature.from_callable(
|
322
|
+
Foo.foo, auto_typing=True, auto_doc=True
|
323
|
+
).to_schema()
|
324
|
+
self.assertEqual(
|
325
|
+
schema,
|
326
|
+
class_schema.Schema(
|
327
|
+
[
|
328
|
+
class_schema.Field('a', vs.Int(), 'An int.'),
|
329
|
+
class_schema.Field(
|
330
|
+
'args', vs.List(vs.Any(), default=[]), 'Varargs.'
|
331
|
+
),
|
332
|
+
class_schema.Field('b', vs.Str(default='x'), 'A str.'),
|
333
|
+
class_schema.Field(ks.StrKey(), vs.Any(), 'Kwargs.'),
|
334
|
+
],
|
335
|
+
allow_nonconst_keys=True,
|
336
|
+
)
|
337
|
+
)
|
338
|
+
self.assertEqual(
|
339
|
+
schema.name, f'{Foo.foo.__module__}.{Foo.foo.__qualname__}'
|
340
|
+
)
|
341
|
+
self.assertEqual(schema.description, 'Function foo.')
|
342
|
+
self.assertTrue(schema.allow_nonconst_keys)
|
343
|
+
self.assertEqual(
|
344
|
+
schema.metadata,
|
345
|
+
dict(
|
346
|
+
init_arg_list=['a', '*args'],
|
347
|
+
varargs_name='args',
|
348
|
+
varkw_name='kwargs',
|
349
|
+
returns=vs.Str(),
|
350
|
+
)
|
351
|
+
)
|
352
|
+
|
353
|
+
def test_make_function(self):
|
354
|
+
"""Tests `Signature.make_function`."""
|
355
|
+
|
356
|
+
def func1(x, y=1) -> int:
|
357
|
+
del x, y
|
358
|
+
|
359
|
+
def func2(x=1, *, y):
|
360
|
+
del x, y
|
361
|
+
|
362
|
+
def func3(x=1, *y): # pylint: disable=keyword-arg-before-vararg
|
363
|
+
del x, y
|
364
|
+
|
365
|
+
def func4(*y):
|
366
|
+
del y
|
367
|
+
|
368
|
+
def func5(*, x=1, y):
|
369
|
+
del x, y
|
370
|
+
|
371
|
+
def func6(x=1, *, y, **z) -> str:
|
372
|
+
del x, y, z
|
373
|
+
|
374
|
+
for func in [func1, func2, func3, func4, func5, func6]:
|
375
|
+
new_func = callable_signature.signature(func).make_function(['pass'])
|
376
|
+
old_signature = inspect.signature(func)
|
377
|
+
new_signature = inspect.signature(new_func)
|
378
|
+
self.assertEqual(old_signature, new_signature)
|
379
|
+
|
380
|
+
|
381
|
+
class FromCallableTest(unittest.TestCase):
|
382
|
+
"""Tests for `Signature.from_callable`."""
|
81
383
|
|
82
384
|
def test_function(self):
|
83
|
-
"""Tests `
|
385
|
+
"""Tests `from_callable` on regular functions."""
|
84
386
|
|
85
|
-
def foo(a, b: int = 1, **kwargs):
|
387
|
+
def foo(a, *, b: int = 1, **kwargs):
|
86
388
|
del a, b, kwargs
|
87
389
|
|
88
|
-
signature =
|
390
|
+
signature = Signature.from_callable(foo)
|
89
391
|
self.assertEqual(
|
90
392
|
signature.callable_type, callable_signature.CallableType.FUNCTION)
|
91
393
|
self.assertEqual(signature.args, [
|
92
|
-
|
93
|
-
|
94
|
-
|
394
|
+
Argument('a', Argument.Kind.POSITIONAL_OR_KEYWORD, vs.Any()),
|
395
|
+
])
|
396
|
+
self.assertEqual(signature.kwonlyargs, [
|
397
|
+
Argument(
|
398
|
+
'b', Argument.Kind.KEYWORD_ONLY, vs.Any(default=1).annotate(int)
|
399
|
+
),
|
95
400
|
])
|
96
|
-
self.assertEqual(signature.kwonlyargs, [])
|
97
401
|
self.assertIsNone(signature.varargs)
|
98
|
-
self.assertEqual(
|
99
|
-
|
402
|
+
self.assertEqual(
|
403
|
+
signature.varkw,
|
404
|
+
Argument(
|
405
|
+
'kwargs',
|
406
|
+
Argument.Kind.VAR_KEYWORD,
|
407
|
+
vs.Dict(vs.Any())
|
408
|
+
)
|
409
|
+
)
|
100
410
|
self.assertFalse(signature.has_varargs)
|
101
411
|
self.assertTrue(signature.has_varkw)
|
102
412
|
self.assertTrue(signature.has_wildcard_args)
|
@@ -107,12 +417,14 @@ class SignatureTest(unittest.TestCase):
|
|
107
417
|
self.assertEqual(signature.get_value_spec('x'), vs.Any())
|
108
418
|
|
109
419
|
def test_lambda(self):
|
110
|
-
"""Tests `
|
111
|
-
signature =
|
420
|
+
"""Tests `from_callable` on lambda function."""
|
421
|
+
signature = Signature.from_callable(lambda x: x)
|
112
422
|
self.assertEqual(
|
113
423
|
signature.callable_type, callable_signature.CallableType.FUNCTION)
|
114
424
|
self.assertEqual(
|
115
|
-
signature.args,
|
425
|
+
signature.args,
|
426
|
+
[Argument('x', Argument.Kind.POSITIONAL_OR_KEYWORD, vs.Any())]
|
427
|
+
)
|
116
428
|
self.assertEqual(signature.kwonlyargs, [])
|
117
429
|
self.assertIsNone(signature.varargs)
|
118
430
|
self.assertIsNone(signature.varkw)
|
@@ -122,7 +434,7 @@ class SignatureTest(unittest.TestCase):
|
|
122
434
|
self.assertIsNone(signature.get_value_spec('y'))
|
123
435
|
|
124
436
|
def test_method(self):
|
125
|
-
"""Tests
|
437
|
+
"""Tests `from_callable` on class methods."""
|
126
438
|
|
127
439
|
class A:
|
128
440
|
|
@@ -139,163 +451,283 @@ class SignatureTest(unittest.TestCase):
|
|
139
451
|
return z
|
140
452
|
|
141
453
|
# Test class static method.
|
142
|
-
signature =
|
454
|
+
signature = Signature.from_callable(A.foo)
|
143
455
|
self.assertEqual(
|
144
456
|
signature.callable_type, callable_signature.CallableType.METHOD)
|
145
457
|
self.assertEqual(
|
146
458
|
signature.args,
|
147
|
-
[
|
148
|
-
'x',
|
459
|
+
[Argument(
|
460
|
+
'x',
|
461
|
+
Argument.Kind.POSITIONAL_OR_KEYWORD,
|
462
|
+
vs.Any(default=1).annotate(int)
|
463
|
+
)]
|
464
|
+
)
|
149
465
|
self.assertEqual(signature.kwonlyargs, [])
|
150
466
|
|
151
467
|
# Test instance method.
|
152
|
-
signature =
|
468
|
+
signature = Signature.from_callable(A().bar)
|
153
469
|
self.assertEqual(
|
154
470
|
signature.callable_type, callable_signature.CallableType.METHOD)
|
155
471
|
self.assertEqual(
|
156
472
|
signature.args,
|
157
|
-
[
|
473
|
+
[Argument(
|
474
|
+
'y', Argument.Kind.POSITIONAL_OR_KEYWORD, vs.Any().annotate(int)
|
475
|
+
)]
|
476
|
+
)
|
158
477
|
self.assertEqual(
|
159
478
|
signature.kwonlyargs,
|
160
|
-
[
|
479
|
+
[Argument('z', Argument.Kind.KEYWORD_ONLY, vs.Any(default=1))]
|
480
|
+
)
|
161
481
|
self.assertEqual(
|
162
482
|
signature.varargs,
|
163
|
-
|
483
|
+
Argument(
|
484
|
+
'args',
|
485
|
+
Argument.Kind.VAR_POSITIONAL,
|
486
|
+
vs.List(vs.Any(), default=[])
|
487
|
+
)
|
488
|
+
)
|
164
489
|
self.assertTrue(signature.has_varargs)
|
165
490
|
self.assertFalse(signature.has_varkw)
|
166
491
|
|
167
492
|
# Test unbound instance method
|
168
|
-
signature =
|
493
|
+
signature = Signature.from_callable(A.bar)
|
169
494
|
self.assertEqual(
|
170
495
|
signature.callable_type, callable_signature.CallableType.FUNCTION)
|
171
496
|
self.assertEqual(signature.args, [
|
172
|
-
|
173
|
-
|
497
|
+
Argument('self', Argument.Kind.POSITIONAL_OR_KEYWORD, vs.Any()),
|
498
|
+
Argument(
|
499
|
+
'y', Argument.Kind.POSITIONAL_OR_KEYWORD, vs.Any().annotate(int)
|
500
|
+
)
|
174
501
|
])
|
175
502
|
self.assertEqual(
|
176
503
|
signature.kwonlyargs,
|
177
|
-
[
|
504
|
+
[Argument('z', Argument.Kind.KEYWORD_ONLY, vs.Any(default=1))]
|
505
|
+
)
|
178
506
|
self.assertEqual(
|
179
507
|
signature.varargs,
|
180
|
-
|
508
|
+
Argument(
|
509
|
+
'args',
|
510
|
+
Argument.Kind.VAR_POSITIONAL,
|
511
|
+
vs.List(vs.Any(), default=[])
|
512
|
+
)
|
513
|
+
)
|
181
514
|
self.assertTrue(signature.has_varargs)
|
182
515
|
self.assertFalse(signature.has_varkw)
|
183
516
|
|
184
517
|
# Test object as callable.
|
185
|
-
signature =
|
518
|
+
signature = Signature.from_callable(A())
|
186
519
|
self.assertEqual(
|
187
520
|
signature.callable_type, callable_signature.CallableType.METHOD)
|
188
521
|
self.assertEqual(
|
189
522
|
signature.args,
|
190
|
-
[
|
523
|
+
[Argument(
|
524
|
+
'z', Argument.Kind.POSITIONAL_OR_KEYWORD, vs.Any().annotate(int)
|
525
|
+
)]
|
526
|
+
)
|
191
527
|
self.assertEqual(signature.kwonlyargs, [])
|
192
528
|
self.assertFalse(signature.has_varargs)
|
193
529
|
self.assertTrue(signature.has_varkw)
|
194
530
|
self.assertEqual(
|
195
531
|
signature.varkw,
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
532
|
+
Argument(
|
533
|
+
'kwargs', Argument.Kind.VAR_KEYWORD,
|
534
|
+
vs.Dict(vs.Any())
|
535
|
+
)
|
536
|
+
)
|
200
537
|
|
201
|
-
|
202
|
-
|
538
|
+
def test_class(self):
|
539
|
+
"""Tests `from_callable` on classes."""
|
203
540
|
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
def func3(x=1, *y): # pylint: disable=keyword-arg-before-vararg
|
208
|
-
del x, y
|
541
|
+
class A:
|
542
|
+
def __init__(self, x: int, *, y: str, **kwargs):
|
543
|
+
"""Constructor.
|
209
544
|
|
210
|
-
|
211
|
-
|
545
|
+
Args:
|
546
|
+
x: An int.
|
547
|
+
y: A str.
|
548
|
+
**kwargs: Kwargs.
|
549
|
+
"""
|
212
550
|
|
213
|
-
|
214
|
-
|
551
|
+
signature = Signature.from_callable(A, auto_typing=True, auto_doc=True)
|
552
|
+
self.assertEqual(
|
553
|
+
signature.callable_type, callable_signature.CallableType.METHOD
|
554
|
+
)
|
555
|
+
self.assertEqual(signature.name, A.__name__)
|
556
|
+
self.assertEqual(signature.module_name, A.__module__)
|
557
|
+
self.assertEqual(signature.qualname, A.__qualname__)
|
558
|
+
self.assertIsNone(signature.description)
|
215
559
|
|
216
|
-
|
217
|
-
|
560
|
+
self.assertEqual(
|
561
|
+
signature.args,
|
562
|
+
[Argument(
|
563
|
+
'x', Argument.Kind.POSITIONAL_OR_KEYWORD, vs.Int(),
|
564
|
+
description='An int.'
|
565
|
+
)]
|
566
|
+
)
|
567
|
+
self.assertEqual(
|
568
|
+
signature.kwonlyargs,
|
569
|
+
[Argument(
|
570
|
+
'y', Argument.Kind.KEYWORD_ONLY, vs.Str(),
|
571
|
+
description='A str.'
|
572
|
+
)]
|
573
|
+
)
|
574
|
+
self.assertEqual(
|
575
|
+
signature.varkw,
|
576
|
+
Argument(
|
577
|
+
'kwargs',
|
578
|
+
Argument.Kind.VAR_KEYWORD,
|
579
|
+
vs.Dict(vs.Any()),
|
580
|
+
description='Kwargs.'
|
581
|
+
)
|
582
|
+
)
|
583
|
+
|
584
|
+
@dataclasses.dataclass
|
585
|
+
class B:
|
586
|
+
"""Class B.
|
587
|
+
|
588
|
+
Params:
|
589
|
+
x: An int.
|
590
|
+
y: A str.
|
591
|
+
"""
|
592
|
+
x: int
|
593
|
+
y: str
|
594
|
+
|
595
|
+
signature = Signature.from_callable(B, auto_typing=True, auto_doc=True)
|
596
|
+
self.assertEqual(
|
597
|
+
signature.callable_type, callable_signature.CallableType.METHOD
|
598
|
+
)
|
599
|
+
self.assertEqual(signature.name, B.__name__)
|
600
|
+
self.assertEqual(signature.module_name, B.__module__)
|
601
|
+
self.assertEqual(signature.qualname, B.__qualname__)
|
602
|
+
self.assertEqual(signature.description, 'Class B.')
|
603
|
+
self.assertEqual(
|
604
|
+
signature.args,
|
605
|
+
[
|
606
|
+
Argument(
|
607
|
+
'x', Argument.Kind.POSITIONAL_OR_KEYWORD, vs.Int(),
|
608
|
+
description='An int.'
|
609
|
+
),
|
610
|
+
Argument(
|
611
|
+
'y', Argument.Kind.POSITIONAL_OR_KEYWORD, vs.Str(),
|
612
|
+
description='A str.'
|
613
|
+
)
|
614
|
+
]
|
615
|
+
)
|
616
|
+
|
617
|
+
# Signature for builtin classes
|
618
|
+
signature = callable_signature.signature(bytes)
|
619
|
+
self.assertEqual(
|
620
|
+
signature.callable_type, callable_signature.CallableType.METHOD
|
621
|
+
)
|
622
|
+
self.assertEqual(signature.name, bytes.__name__)
|
623
|
+
self.assertEqual(signature.module_name, bytes.__module__)
|
624
|
+
self.assertEqual(signature.qualname, bytes.__qualname__)
|
625
|
+
self.assertIsNotNone(signature.varargs)
|
626
|
+
self.assertIsNotNone(signature.varkw)
|
218
627
|
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
new_signature = inspect.signature(new_func)
|
223
|
-
self.assertEqual(old_signature, new_signature)
|
628
|
+
def test_signature_with_forward_declarations(self):
|
629
|
+
signature = callable_signature.signature(utils.KeyPath)
|
630
|
+
self.assertIs(signature.get_value_spec('parent').cls, utils.KeyPath)
|
224
631
|
|
225
632
|
|
226
633
|
class FromSchemaTest(unittest.TestCase):
|
227
634
|
"""Tests for `Signature.from_schema`."""
|
228
635
|
|
229
|
-
def
|
636
|
+
def _signature(self, init_arg_list, is_method: bool = True):
|
230
637
|
s = class_schema.Schema([
|
231
638
|
class_schema.Field('x', vs.Int(), 'x'),
|
232
639
|
class_schema.Field('y', vs.Int(), 'y'),
|
640
|
+
# Frozen fields will be ignored.
|
641
|
+
class_schema.Field('v', vs.Bool().freeze(True), 'v'),
|
233
642
|
class_schema.Field('z', vs.List(vs.Int()), 'z'),
|
234
643
|
class_schema.Field(ks.StrKey(), vs.Str(), 'kwargs'),
|
235
644
|
], metadata=dict(init_arg_list=init_arg_list), allow_nonconst_keys=True)
|
236
|
-
return
|
645
|
+
return Signature.from_schema(
|
237
646
|
s, 'bar', 'foo', is_method=is_method)
|
238
647
|
|
239
648
|
def test_classmethod_with_regular_args(self):
|
240
649
|
self.assertEqual(
|
241
|
-
self.
|
242
|
-
|
650
|
+
self._signature(['x', 'y', 'z']),
|
651
|
+
Signature(
|
243
652
|
callable_type=callable_signature.CallableType.FUNCTION,
|
244
653
|
module_name='bar',
|
245
654
|
name='foo',
|
246
655
|
args=[
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
656
|
+
Argument('self', Argument.Kind.POSITIONAL_OR_KEYWORD, vs.Any()),
|
657
|
+
Argument('x', Argument.Kind.POSITIONAL_OR_KEYWORD, vs.Int()),
|
658
|
+
Argument('y', Argument.Kind.POSITIONAL_OR_KEYWORD, vs.Int()),
|
659
|
+
Argument(
|
660
|
+
'z', Argument.Kind.POSITIONAL_OR_KEYWORD, vs.List(vs.Int())
|
661
|
+
),
|
251
662
|
],
|
252
|
-
varkw=
|
663
|
+
varkw=Argument(
|
664
|
+
'kwargs',
|
665
|
+
Argument.Kind.VAR_KEYWORD,
|
666
|
+
vs.Dict(vs.Str())
|
667
|
+
)
|
668
|
+
)
|
669
|
+
)
|
253
670
|
|
254
671
|
def test_function_with_varargs(self):
|
255
672
|
self.assertEqual(
|
256
|
-
self.
|
257
|
-
|
673
|
+
self._signature(['x', '*z'], is_method=False),
|
674
|
+
Signature(
|
258
675
|
callable_type=callable_signature.CallableType.FUNCTION,
|
259
676
|
module_name='bar',
|
260
677
|
name='foo',
|
261
678
|
args=[
|
262
|
-
|
679
|
+
Argument('x', Argument.Kind.POSITIONAL_OR_KEYWORD, vs.Int()),
|
263
680
|
],
|
264
681
|
kwonlyargs=[
|
265
|
-
|
682
|
+
Argument('y', Argument.Kind.KEYWORD_ONLY, vs.Int()),
|
266
683
|
],
|
267
|
-
varargs=
|
268
|
-
|
684
|
+
varargs=Argument(
|
685
|
+
'z', Argument.Kind.VAR_POSITIONAL, vs.List(vs.Int())
|
686
|
+
),
|
687
|
+
varkw=Argument(
|
688
|
+
'kwargs',
|
689
|
+
Argument.Kind.VAR_KEYWORD,
|
690
|
+
vs.Dict(vs.Str())
|
691
|
+
)
|
692
|
+
)
|
693
|
+
)
|
269
694
|
|
270
695
|
def test_classmethod_with_kwonly_args(self):
|
271
696
|
self.assertEqual(
|
272
|
-
self.
|
273
|
-
|
697
|
+
self._signature([]),
|
698
|
+
Signature(
|
274
699
|
callable_type=callable_signature.CallableType.FUNCTION,
|
275
700
|
module_name='bar',
|
276
701
|
name='foo',
|
277
702
|
args=[
|
278
|
-
|
703
|
+
Argument('self', Argument.Kind.POSITIONAL_OR_KEYWORD, vs.Any()),
|
279
704
|
],
|
280
705
|
kwonlyargs=[
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
'z', vs.List(vs.Int())
|
706
|
+
Argument('x', Argument.Kind.KEYWORD_ONLY, vs.Int()),
|
707
|
+
Argument('y', Argument.Kind.KEYWORD_ONLY, vs.Int()),
|
708
|
+
Argument(
|
709
|
+
'z', Argument.Kind.KEYWORD_ONLY, vs.List(vs.Int())
|
710
|
+
),
|
285
711
|
],
|
286
|
-
varkw=
|
712
|
+
varkw=Argument(
|
713
|
+
'kwargs',
|
714
|
+
Argument.Kind.VAR_KEYWORD,
|
715
|
+
vs.Dict(vs.Str())
|
716
|
+
)
|
717
|
+
)
|
718
|
+
)
|
287
719
|
|
288
720
|
def test_bad_cases(self):
|
289
721
|
with self.assertRaisesRegex(
|
290
|
-
|
722
|
+
TypeError,
|
291
723
|
'Variable positional argument \'x\' should have a value of '
|
292
724
|
'`pg.typing.List` type'):
|
293
|
-
_ = self.
|
725
|
+
_ = self._signature(['*x'])
|
294
726
|
|
295
727
|
with self.assertRaisesRegex(
|
296
728
|
ValueError,
|
297
729
|
'Argument \'a\' is not a symbolic field.'):
|
298
|
-
_ =
|
730
|
+
_ = Signature.from_schema(
|
299
731
|
class_schema.Schema([], metadata=dict(init_arg_list=['a'])),
|
300
732
|
'__main__', 'foo')
|
301
733
|
|
@@ -304,7 +736,95 @@ class FromSchemaTest(unittest.TestCase):
|
|
304
736
|
|
305
737
|
with self.assertRaisesRegex(
|
306
738
|
TypeError, '.*__call__ is not a method'):
|
307
|
-
|
739
|
+
Signature.from_callable(Foo())
|
740
|
+
|
741
|
+
|
742
|
+
class GetSchemaTest(unittest.TestCase):
|
743
|
+
"""Tests for `schema`."""
|
744
|
+
|
745
|
+
def test_function_schema(self):
|
746
|
+
def foo(x: int, *args, y: str, **kwargs) -> float:
|
747
|
+
"""A function.
|
748
|
+
|
749
|
+
Args:
|
750
|
+
x: Input 1.
|
751
|
+
*args: Variable positional args.
|
752
|
+
y: Input 2.
|
753
|
+
**kwargs: Variable keyword args.
|
754
|
+
|
755
|
+
Returns:
|
756
|
+
The result.
|
757
|
+
"""
|
758
|
+
del x, y, args, kwargs
|
759
|
+
|
760
|
+
schema = callable_signature.schema(foo, auto_typing=True, auto_doc=True)
|
761
|
+
self.assertEqual(schema.name, f'{foo.__module__}.{foo.__qualname__}')
|
762
|
+
self.assertEqual(schema.description, 'A function.')
|
763
|
+
self.assertEqual(
|
764
|
+
list(schema.fields.values()),
|
765
|
+
[
|
766
|
+
class_schema.Field('x', vs.Int(), description='Input 1.'),
|
767
|
+
class_schema.Field(
|
768
|
+
'args',
|
769
|
+
vs.List(vs.Any(), default=[]),
|
770
|
+
description='Variable positional args.',
|
771
|
+
),
|
772
|
+
class_schema.Field('y', vs.Str(), description='Input 2.'),
|
773
|
+
class_schema.Field(
|
774
|
+
ks.StrKey(),
|
775
|
+
vs.Any(),
|
776
|
+
description='Variable keyword args.',
|
777
|
+
),
|
778
|
+
],
|
779
|
+
)
|
780
|
+
|
781
|
+
def test_schema_on_symbolic_classes(self):
|
782
|
+
|
783
|
+
class A:
|
784
|
+
pass
|
785
|
+
|
786
|
+
setattr(A, '__schema__', class_schema.create_schema([]))
|
787
|
+
self.assertIs(callable_signature.schema(A), A.__schema__)
|
788
|
+
|
789
|
+
def test_class_init_schema(self):
|
790
|
+
class A:
|
791
|
+
|
792
|
+
def __init__(self, x: int, *args, y: str, **kwargs) -> float:
|
793
|
+
"""Constructor.
|
794
|
+
|
795
|
+
Args:
|
796
|
+
x: Input 1.
|
797
|
+
*args: Variable positional args.
|
798
|
+
y: Input 2.
|
799
|
+
**kwargs: Variable keyword args.
|
800
|
+
|
801
|
+
Returns:
|
802
|
+
The result.
|
803
|
+
"""
|
804
|
+
del x, y, args, kwargs
|
805
|
+
|
806
|
+
schema = callable_signature.schema(
|
807
|
+
A.__init__, auto_typing=True, auto_doc=True, remove_self=True
|
808
|
+
)
|
809
|
+
self.assertEqual(schema.name, f'{A.__module__}.{A.__init__.__qualname__}')
|
810
|
+
self.assertEqual(schema.description, 'Constructor.')
|
811
|
+
self.assertEqual(
|
812
|
+
list(schema.fields.values()),
|
813
|
+
[
|
814
|
+
class_schema.Field('x', vs.Int(), description='Input 1.'),
|
815
|
+
class_schema.Field(
|
816
|
+
'args',
|
817
|
+
vs.List(vs.Any(), default=[]),
|
818
|
+
description='Variable positional args.',
|
819
|
+
),
|
820
|
+
class_schema.Field('y', vs.Str(), description='Input 2.'),
|
821
|
+
class_schema.Field(
|
822
|
+
ks.StrKey(),
|
823
|
+
vs.Any(),
|
824
|
+
description='Variable keyword args.',
|
825
|
+
),
|
826
|
+
],
|
827
|
+
)
|
308
828
|
|
309
829
|
|
310
830
|
if __name__ == '__main__':
|