langfun 0.0.2.dev20240527__py3-none-any.whl → 0.0.2.dev20240531__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.
Potentially problematic release.
This version of langfun might be problematic. Click here for more details.
- langfun/__init__.py +2 -0
- langfun/core/language_model_test.py +3 -2
- langfun/core/llms/google_genai_test.py +1 -1
- langfun/core/llms/openai_test.py +1 -1
- langfun/core/llms/vertexai_test.py +1 -1
- langfun/core/message.py +1 -1
- langfun/core/message_test.py +12 -9
- langfun/core/modalities/__init__.py +4 -0
- langfun/core/modalities/audio.py +30 -0
- langfun/core/modalities/audio_test.py +63 -0
- langfun/core/modalities/ms_office.py +83 -0
- langfun/core/modalities/ms_office_test.py +312 -0
- langfun/core/modality.py +2 -2
- langfun/core/modality_test.py +1 -1
- langfun/core/structured/__init__.py +2 -0
- langfun/core/structured/completion.py +3 -1
- langfun/core/structured/completion_test.py +2 -2
- langfun/core/structured/mapping.py +1 -5
- langfun/core/structured/prompting.py +0 -4
- langfun/core/structured/prompting_test.py +8 -6
- langfun/core/structured/schema.py +88 -42
- langfun/core/structured/schema_test.py +87 -34
- langfun/core/template_test.py +1 -1
- {langfun-0.0.2.dev20240527.dist-info → langfun-0.0.2.dev20240531.dist-info}/METADATA +3 -1
- {langfun-0.0.2.dev20240527.dist-info → langfun-0.0.2.dev20240531.dist-info}/RECORD +28 -24
- {langfun-0.0.2.dev20240527.dist-info → langfun-0.0.2.dev20240531.dist-info}/LICENSE +0 -0
- {langfun-0.0.2.dev20240527.dist-info → langfun-0.0.2.dev20240531.dist-info}/WHEEL +0 -0
- {langfun-0.0.2.dev20240527.dist-info → langfun-0.0.2.dev20240531.dist-info}/top_level.txt +0 -0
@@ -16,6 +16,7 @@
|
|
16
16
|
import abc
|
17
17
|
import inspect
|
18
18
|
import io
|
19
|
+
import re
|
19
20
|
import textwrap
|
20
21
|
import typing
|
21
22
|
from typing import Any, Literal, Sequence, Type, Union
|
@@ -24,6 +25,17 @@ from langfun.core.coding.python import correction
|
|
24
25
|
import pyglove as pg
|
25
26
|
|
26
27
|
|
28
|
+
def include_method_in_prompt(method):
|
29
|
+
"""Decorator to include a method in the class definition of the prompt."""
|
30
|
+
setattr(method, '__show_in_prompt__', True)
|
31
|
+
return method
|
32
|
+
|
33
|
+
|
34
|
+
def should_include_method_in_prompt(method):
|
35
|
+
"""Returns true if the method should be shown in the prompt."""
|
36
|
+
return getattr(method, '__show_in_prompt__', False)
|
37
|
+
|
38
|
+
|
27
39
|
def parse_value_spec(value) -> pg.typing.ValueSpec:
|
28
40
|
"""Parses a PyGlove ValueSpec equivalence into a ValueSpec."""
|
29
41
|
if isinstance(value, pg.typing.ValueSpec):
|
@@ -163,9 +175,12 @@ class Schema(lf.NaturalLanguageFormattable, pg.Object):
|
|
163
175
|
|
164
176
|
def class_dependencies(
|
165
177
|
self,
|
178
|
+
include_base_classes: bool = True,
|
166
179
|
include_subclasses: bool = True) -> list[Type[Any]]:
|
167
180
|
"""Returns a list of class dependencies for current schema."""
|
168
|
-
return class_dependencies(
|
181
|
+
return class_dependencies(
|
182
|
+
self.spec, include_base_classes, include_subclasses
|
183
|
+
)
|
169
184
|
|
170
185
|
@classmethod
|
171
186
|
def from_value(cls, value) -> 'Schema':
|
@@ -198,11 +213,12 @@ def class_dependencies(
|
|
198
213
|
Type[pg.Object],
|
199
214
|
tuple[Union[pg.typing.ValueSpec, Type[pg.Object]], ...],
|
200
215
|
],
|
216
|
+
include_base_classes: bool = True,
|
201
217
|
include_subclasses: bool = True,
|
202
218
|
) -> list[Type[Any]]:
|
203
219
|
"""Returns a list of class dependencies from a value or specs."""
|
204
220
|
if isinstance(value_or_spec, Schema):
|
205
|
-
|
221
|
+
value_or_spec = value_or_spec.spec
|
206
222
|
|
207
223
|
if inspect.isclass(value_or_spec) or isinstance(
|
208
224
|
value_or_spec, pg.typing.ValueSpec
|
@@ -236,13 +252,14 @@ def class_dependencies(
|
|
236
252
|
if vs.cls not in seen:
|
237
253
|
seen.add(vs.cls)
|
238
254
|
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
255
|
+
if include_base_classes:
|
256
|
+
# Add base classes as dependencies.
|
257
|
+
for base_cls in vs.cls.__bases__:
|
258
|
+
# We only keep track of user-defined symbolic classes.
|
259
|
+
if base_cls is not object and base_cls is not pg.Object:
|
260
|
+
_fill_dependencies(
|
261
|
+
pg.typing.Object(base_cls), include_subclasses=False
|
262
|
+
)
|
246
263
|
|
247
264
|
# Add members as dependencies.
|
248
265
|
for field in _pg_schema(vs.cls).values():
|
@@ -301,7 +318,6 @@ class SchemaPythonRepr(SchemaRepr):
|
|
301
318
|
schema: Schema,
|
302
319
|
*,
|
303
320
|
include_result_definition: bool = True,
|
304
|
-
include_methods: bool = False,
|
305
321
|
markdown: bool = True,
|
306
322
|
**kwargs,
|
307
323
|
) -> str:
|
@@ -309,15 +325,27 @@ class SchemaPythonRepr(SchemaRepr):
|
|
309
325
|
if include_result_definition:
|
310
326
|
ret += self.result_definition(schema)
|
311
327
|
class_definition_str = self.class_definitions(
|
312
|
-
schema, markdown=markdown,
|
328
|
+
schema, markdown=markdown, **kwargs
|
313
329
|
)
|
314
330
|
if class_definition_str:
|
315
331
|
ret += f'\n\n{class_definition_str}'
|
316
332
|
return ret.strip()
|
317
333
|
|
318
|
-
def class_definitions(
|
319
|
-
|
320
|
-
|
334
|
+
def class_definitions(
|
335
|
+
self,
|
336
|
+
schema: Schema,
|
337
|
+
additional_dependencies: list[Type[Any]] | None = None,
|
338
|
+
**kwargs
|
339
|
+
) -> str | None:
|
340
|
+
"""Returns a string containing of class definitions from a schema."""
|
341
|
+
deps = schema.class_dependencies(
|
342
|
+
include_base_classes=False, include_subclasses=True
|
343
|
+
)
|
344
|
+
allowed_dependencies = set(deps)
|
345
|
+
if additional_dependencies:
|
346
|
+
allowed_dependencies.update(additional_dependencies)
|
347
|
+
return class_definitions(
|
348
|
+
deps, allowed_dependencies=allowed_dependencies, **kwargs)
|
321
349
|
|
322
350
|
def result_definition(self, schema: Schema) -> str:
|
323
351
|
return annotation(schema.spec)
|
@@ -331,8 +359,7 @@ def source_form(value, markdown: bool = False) -> str:
|
|
331
359
|
def class_definitions(
|
332
360
|
classes: Sequence[Type[Any]],
|
333
361
|
*,
|
334
|
-
|
335
|
-
include_methods: bool = False,
|
362
|
+
allowed_dependencies: set[Type[Any]] | None = None,
|
336
363
|
strict: bool = False,
|
337
364
|
markdown: bool = False,
|
338
365
|
) -> str | None:
|
@@ -347,8 +374,7 @@ def class_definitions(
|
|
347
374
|
class_definition(
|
348
375
|
cls,
|
349
376
|
strict=strict,
|
350
|
-
|
351
|
-
include_methods=include_methods,
|
377
|
+
allowed_dependencies=allowed_dependencies,
|
352
378
|
)
|
353
379
|
)
|
354
380
|
ret = def_str.getvalue()
|
@@ -360,8 +386,7 @@ def class_definitions(
|
|
360
386
|
def class_definition(
|
361
387
|
cls,
|
362
388
|
strict: bool = False,
|
363
|
-
|
364
|
-
include_methods: bool = False,
|
389
|
+
allowed_dependencies: set[Type[Any]] | None = None,
|
365
390
|
) -> str:
|
366
391
|
"""Returns the Python class definition."""
|
367
392
|
out = io.StringIO()
|
@@ -369,7 +394,7 @@ def class_definition(
|
|
369
394
|
eligible_bases = []
|
370
395
|
for base_cls in cls.__bases__:
|
371
396
|
if base_cls is not object:
|
372
|
-
if
|
397
|
+
if allowed_dependencies is None or base_cls in allowed_dependencies:
|
373
398
|
eligible_bases.append(base_cls.__name__)
|
374
399
|
|
375
400
|
if eligible_bases:
|
@@ -406,32 +431,41 @@ def class_definition(
|
|
406
431
|
out.write(' # ')
|
407
432
|
out.write(line)
|
408
433
|
out.write('\n')
|
409
|
-
out.write(f' {field.key}: {annotation(field.value, strict=strict)}')
|
410
|
-
out.write('\n')
|
411
|
-
empty_class = False
|
412
434
|
|
413
|
-
|
414
|
-
|
415
|
-
out.write('\n')
|
416
|
-
out.write(
|
417
|
-
textwrap.indent(
|
418
|
-
inspect.cleandoc('\n' + inspect.getsource(method)), ' ' * 2)
|
435
|
+
annotation_str = annotation(
|
436
|
+
field.value, strict=strict, allowed_dependencies=allowed_dependencies
|
419
437
|
)
|
438
|
+
out.write(f' {field.key}: {annotation_str}')
|
420
439
|
out.write('\n')
|
421
440
|
empty_class = False
|
422
441
|
|
442
|
+
for method in _iter_newly_defined_methods(cls, allowed_dependencies):
|
443
|
+
source = inspect.getsource(method)
|
444
|
+
# Remove decorators from the method definition.
|
445
|
+
source = re.sub(r'\s*@.*\.include_method_in_prompt.*\n', '', source)
|
446
|
+
out.write('\n')
|
447
|
+
out.write(
|
448
|
+
textwrap.indent(
|
449
|
+
inspect.cleandoc('\n' + source), ' ' * 2)
|
450
|
+
)
|
451
|
+
out.write('\n')
|
452
|
+
empty_class = False
|
453
|
+
|
423
454
|
if empty_class:
|
424
455
|
out.write(' pass\n')
|
425
456
|
return out.getvalue()
|
426
457
|
|
427
458
|
|
428
|
-
def _iter_newly_defined_methods(
|
429
|
-
|
459
|
+
def _iter_newly_defined_methods(
|
460
|
+
cls, allowed_dependencies: set[Type[Any]] | None):
|
461
|
+
names = {attr_name: True for attr_name in dir(cls)}
|
430
462
|
for base in cls.__bases__:
|
431
|
-
|
432
|
-
|
463
|
+
if allowed_dependencies is None or base in allowed_dependencies:
|
464
|
+
for name in dir(base):
|
465
|
+
names.pop(name, None)
|
466
|
+
for name in names.keys():
|
433
467
|
attr = getattr(cls, name)
|
434
|
-
if callable(attr):
|
468
|
+
if callable(attr) and should_include_method_in_prompt(attr):
|
435
469
|
yield attr
|
436
470
|
|
437
471
|
|
@@ -439,8 +473,12 @@ def annotation(
|
|
439
473
|
vs: pg.typing.ValueSpec,
|
440
474
|
annotate_optional: bool = True,
|
441
475
|
strict: bool = False,
|
476
|
+
allowed_dependencies: set[Type[Any]] | None = None,
|
442
477
|
) -> str:
|
443
478
|
"""Returns the annotation string for a value spec."""
|
479
|
+
child_annotation_kwargs = dict(
|
480
|
+
strict=strict, allowed_dependencies=allowed_dependencies
|
481
|
+
)
|
444
482
|
if isinstance(vs, pg.typing.Any):
|
445
483
|
return 'Any'
|
446
484
|
elif isinstance(vs, pg.typing.Enum):
|
@@ -449,7 +487,7 @@ def annotation(
|
|
449
487
|
elif isinstance(vs, pg.typing.Union):
|
450
488
|
candidate_str = ', '.join(
|
451
489
|
[
|
452
|
-
annotation(c, annotate_optional=False,
|
490
|
+
annotation(c, annotate_optional=False, **child_annotation_kwargs)
|
453
491
|
for c in vs.candidates
|
454
492
|
]
|
455
493
|
)
|
@@ -485,20 +523,23 @@ def annotation(
|
|
485
523
|
)
|
486
524
|
x += '(' + ', '.join(constraints) + ')'
|
487
525
|
elif isinstance(vs, pg.typing.Object):
|
488
|
-
|
526
|
+
if allowed_dependencies is None or vs.cls in allowed_dependencies:
|
527
|
+
x = vs.cls.__name__
|
528
|
+
else:
|
529
|
+
x = 'Any'
|
489
530
|
elif isinstance(vs, pg.typing.List):
|
490
|
-
item_str = annotation(vs.element.value,
|
531
|
+
item_str = annotation(vs.element.value, **child_annotation_kwargs)
|
491
532
|
x = f'list[{item_str}]'
|
492
533
|
elif isinstance(vs, pg.typing.Tuple):
|
493
534
|
elem_str = ', '.join(
|
494
|
-
[annotation(el.value,
|
535
|
+
[annotation(el.value, **child_annotation_kwargs) for el in vs.elements]
|
495
536
|
)
|
496
537
|
x = f'tuple[{elem_str}]'
|
497
538
|
elif isinstance(vs, pg.typing.Dict):
|
498
539
|
kv_pairs = None
|
499
540
|
if vs.schema is not None:
|
500
541
|
kv_pairs = [
|
501
|
-
(k, annotation(f.value,
|
542
|
+
(k, annotation(f.value, **child_annotation_kwargs))
|
502
543
|
for k, f in vs.schema.items()
|
503
544
|
if isinstance(k, pg.typing.ConstStrKey)
|
504
545
|
]
|
@@ -509,7 +550,7 @@ def annotation(
|
|
509
550
|
if strict:
|
510
551
|
x = f'pg.typing.Dict({x})'
|
511
552
|
elif vs.schema and vs.schema.dynamic_field:
|
512
|
-
v = annotation(vs.schema.dynamic_field.value,
|
553
|
+
v = annotation(vs.schema.dynamic_field.value, **child_annotation_kwargs)
|
513
554
|
x = f'dict[str, {v}]'
|
514
555
|
else:
|
515
556
|
x = 'dict[str, Any]'
|
@@ -604,7 +645,12 @@ class ValuePythonRepr(ValueRepr):
|
|
604
645
|
cls_schema = Schema.from_value(value)
|
605
646
|
if isinstance(cls_schema.spec, pg.typing.Object):
|
606
647
|
object_code = SchemaPythonRepr().class_definitions(
|
607
|
-
cls_schema,
|
648
|
+
cls_schema,
|
649
|
+
markdown=markdown,
|
650
|
+
# We add `pg.Object` as additional dependencies to the class
|
651
|
+
# definition so exemplars for class generation could show
|
652
|
+
# pg.Object as their bases.
|
653
|
+
additional_dependencies=[pg.Object]
|
608
654
|
)
|
609
655
|
assert object_code is not None
|
610
656
|
return object_code
|
@@ -283,9 +283,10 @@ class SchemaPythonReprTest(unittest.TestCase):
|
|
283
283
|
value_spec: pg.typing.ValueSpec,
|
284
284
|
expected_annotation: str,
|
285
285
|
strict: bool = False,
|
286
|
+
**kwargs,
|
286
287
|
) -> None:
|
287
288
|
self.assertEqual(
|
288
|
-
schema_lib.annotation(value_spec, strict=strict),
|
289
|
+
schema_lib.annotation(value_spec, strict=strict, **kwargs),
|
289
290
|
expected_annotation,
|
290
291
|
)
|
291
292
|
|
@@ -361,11 +362,27 @@ class SchemaPythonReprTest(unittest.TestCase):
|
|
361
362
|
self.assert_annotation(
|
362
363
|
pg.typing.Object(Activity).noneable(), 'Activity | None'
|
363
364
|
)
|
365
|
+
self.assert_annotation(
|
366
|
+
pg.typing.Object(Activity).noneable(), 'Activity | None',
|
367
|
+
allowed_dependencies=set([Activity]),
|
368
|
+
)
|
369
|
+
self.assert_annotation(
|
370
|
+
pg.typing.Object(Activity).noneable(), 'Any | None',
|
371
|
+
allowed_dependencies=set(),
|
372
|
+
)
|
364
373
|
|
365
374
|
# List.
|
366
375
|
self.assert_annotation(
|
367
376
|
pg.typing.List(pg.typing.Object(Activity)), 'list[Activity]'
|
368
377
|
)
|
378
|
+
self.assert_annotation(
|
379
|
+
pg.typing.List(pg.typing.Object(Activity)), 'list[Activity]',
|
380
|
+
allowed_dependencies=set([Activity]),
|
381
|
+
)
|
382
|
+
self.assert_annotation(
|
383
|
+
pg.typing.List(pg.typing.Object(Activity)), 'list[Any]',
|
384
|
+
allowed_dependencies=set(),
|
385
|
+
)
|
369
386
|
self.assert_annotation(
|
370
387
|
pg.typing.List(pg.typing.Object(Activity)).noneable(),
|
371
388
|
'list[Activity] | None',
|
@@ -377,16 +394,35 @@ class SchemaPythonReprTest(unittest.TestCase):
|
|
377
394
|
|
378
395
|
# Tuple.
|
379
396
|
self.assert_annotation(
|
380
|
-
pg.typing.Tuple([
|
397
|
+
pg.typing.Tuple([Activity, pg.typing.Str()]), 'tuple[Activity, str]'
|
398
|
+
)
|
399
|
+
self.assert_annotation(
|
400
|
+
pg.typing.Tuple([Activity, pg.typing.Str()]), 'tuple[Activity, str]',
|
401
|
+
allowed_dependencies=set([Activity]),
|
381
402
|
)
|
382
403
|
self.assert_annotation(
|
383
|
-
pg.typing.Tuple([
|
384
|
-
|
404
|
+
pg.typing.Tuple([Activity, pg.typing.Str()]), 'tuple[Any, str]',
|
405
|
+
allowed_dependencies=set(),
|
406
|
+
)
|
407
|
+
self.assert_annotation(
|
408
|
+
pg.typing.Tuple([Activity, pg.typing.Str()]).noneable(),
|
409
|
+
'tuple[Activity, str] | None',
|
385
410
|
)
|
386
411
|
|
387
412
|
# Dict.
|
388
413
|
self.assert_annotation(
|
389
|
-
pg.typing.Dict({'x':
|
414
|
+
pg.typing.Dict({'x': Activity, 'y': str}),
|
415
|
+
'{\'x\': Activity, \'y\': str}'
|
416
|
+
)
|
417
|
+
self.assert_annotation(
|
418
|
+
pg.typing.Dict({'x': Activity, 'y': str}),
|
419
|
+
'{\'x\': Activity, \'y\': str}',
|
420
|
+
allowed_dependencies=set([Activity]),
|
421
|
+
)
|
422
|
+
self.assert_annotation(
|
423
|
+
pg.typing.Dict({'x': Activity, 'y': str}),
|
424
|
+
'{\'x\': Any, \'y\': str}',
|
425
|
+
allowed_dependencies=set(),
|
390
426
|
)
|
391
427
|
self.assert_annotation(
|
392
428
|
pg.typing.Dict({'x': int, 'y': str}),
|
@@ -420,6 +456,13 @@ class SchemaPythonReprTest(unittest.TestCase):
|
|
420
456
|
).noneable(),
|
421
457
|
'Union[Activity, Itinerary, None]',
|
422
458
|
)
|
459
|
+
self.assert_annotation(
|
460
|
+
pg.typing.Union(
|
461
|
+
[pg.typing.Object(Activity), pg.typing.Object(Itinerary)]
|
462
|
+
).noneable(),
|
463
|
+
'Union[Activity, Any, None]',
|
464
|
+
allowed_dependencies=set([Activity]),
|
465
|
+
)
|
423
466
|
|
424
467
|
# Any.
|
425
468
|
self.assert_annotation(pg.typing.Any(), 'Any')
|
@@ -427,13 +470,13 @@ class SchemaPythonReprTest(unittest.TestCase):
|
|
427
470
|
|
428
471
|
def test_class_definition(self):
|
429
472
|
self.assertEqual(
|
430
|
-
schema_lib.class_definition(Activity),
|
473
|
+
schema_lib.class_definition(Activity, allowed_dependencies=set()),
|
431
474
|
'class Activity:\n description: str\n',
|
432
475
|
)
|
433
476
|
self.assertEqual(
|
434
477
|
schema_lib.class_definition(Itinerary),
|
435
478
|
inspect.cleandoc("""
|
436
|
-
class Itinerary:
|
479
|
+
class Itinerary(Object):
|
437
480
|
\"\"\"A travel itinerary for a day.\"\"\"
|
438
481
|
day: int(min=1)
|
439
482
|
type: Literal['daytime', 'nighttime']
|
@@ -443,7 +486,9 @@ class SchemaPythonReprTest(unittest.TestCase):
|
|
443
486
|
""") + '\n',
|
444
487
|
)
|
445
488
|
self.assertEqual(
|
446
|
-
schema_lib.class_definition(
|
489
|
+
schema_lib.class_definition(
|
490
|
+
PlaceOfInterest, allowed_dependencies=set()
|
491
|
+
),
|
447
492
|
inspect.cleandoc("""
|
448
493
|
class PlaceOfInterest:
|
449
494
|
\"\"\"The name of a place of interest.
|
@@ -459,11 +504,11 @@ class SchemaPythonReprTest(unittest.TestCase):
|
|
459
504
|
pass
|
460
505
|
|
461
506
|
self.assertEqual(
|
462
|
-
schema_lib.class_definition(A),
|
507
|
+
schema_lib.class_definition(A, allowed_dependencies=set()),
|
463
508
|
'class A:\n pass\n',
|
464
509
|
)
|
465
510
|
self.assertEqual(
|
466
|
-
schema_lib.class_definition(A
|
511
|
+
schema_lib.class_definition(A),
|
467
512
|
'class A(Object):\n pass\n',
|
468
513
|
)
|
469
514
|
|
@@ -471,18 +516,21 @@ class SchemaPythonReprTest(unittest.TestCase):
|
|
471
516
|
x: str
|
472
517
|
__kwargs__: typing.Any
|
473
518
|
|
474
|
-
self.assertEqual(
|
519
|
+
self.assertEqual(
|
520
|
+
schema_lib.class_definition(C), 'class C(Object):\n x: str\n'
|
521
|
+
)
|
475
522
|
|
476
523
|
class D(pg.Object):
|
477
524
|
x: str
|
525
|
+
@schema_lib.include_method_in_prompt
|
478
526
|
def __call__(self, y: int) -> int:
|
479
527
|
return len(self.x) + y
|
480
528
|
|
481
529
|
self.assertEqual(
|
482
|
-
schema_lib.class_definition(D
|
530
|
+
schema_lib.class_definition(D),
|
483
531
|
inspect.cleandoc(
|
484
532
|
"""
|
485
|
-
class D:
|
533
|
+
class D(Object):
|
486
534
|
x: str
|
487
535
|
|
488
536
|
def __call__(self, y: int) -> int:
|
@@ -506,31 +554,28 @@ class SchemaPythonReprTest(unittest.TestCase):
|
|
506
554
|
class A(pg.Object):
|
507
555
|
foo: Foo
|
508
556
|
|
557
|
+
@schema_lib.include_method_in_prompt
|
509
558
|
def foo_value(self) -> int:
|
510
559
|
return self.foo.x
|
511
560
|
|
561
|
+
def baz_value(self) -> str:
|
562
|
+
return 'baz'
|
563
|
+
|
512
564
|
class B(A):
|
513
565
|
bar: Bar
|
514
566
|
foo2: Foo
|
515
567
|
|
568
|
+
@schema_lib.include_method_in_prompt
|
516
569
|
def bar_value(self) -> str:
|
517
570
|
return self.bar.y
|
518
571
|
|
519
572
|
schema = schema_lib.Schema([B])
|
520
573
|
self.assertEqual(
|
521
|
-
schema_lib.SchemaPythonRepr().class_definitions(
|
522
|
-
schema, include_methods=True
|
523
|
-
),
|
574
|
+
schema_lib.SchemaPythonRepr().class_definitions(schema),
|
524
575
|
inspect.cleandoc('''
|
525
576
|
class Foo:
|
526
577
|
x: int
|
527
578
|
|
528
|
-
class A:
|
529
|
-
foo: Foo
|
530
|
-
|
531
|
-
def foo_value(self) -> int:
|
532
|
-
return self.foo.x
|
533
|
-
|
534
579
|
class Bar:
|
535
580
|
"""Class Bar."""
|
536
581
|
y: str
|
@@ -539,13 +584,16 @@ class SchemaPythonReprTest(unittest.TestCase):
|
|
539
584
|
"""Baz(y: str)"""
|
540
585
|
y: str
|
541
586
|
|
542
|
-
class B
|
587
|
+
class B:
|
543
588
|
foo: Foo
|
544
589
|
bar: Bar
|
545
590
|
foo2: Foo
|
546
591
|
|
547
592
|
def bar_value(self) -> str:
|
548
593
|
return self.bar.y
|
594
|
+
|
595
|
+
def foo_value(self) -> int:
|
596
|
+
return self.foo.x
|
549
597
|
''') + '\n',
|
550
598
|
)
|
551
599
|
|
@@ -562,9 +610,6 @@ class SchemaPythonReprTest(unittest.TestCase):
|
|
562
610
|
class Foo:
|
563
611
|
x: int
|
564
612
|
|
565
|
-
class A:
|
566
|
-
foo: Foo
|
567
|
-
|
568
613
|
class Bar:
|
569
614
|
"""Class Bar."""
|
570
615
|
y: str
|
@@ -573,10 +618,16 @@ class SchemaPythonReprTest(unittest.TestCase):
|
|
573
618
|
"""Baz(y: str)"""
|
574
619
|
y: str
|
575
620
|
|
576
|
-
class B
|
621
|
+
class B:
|
577
622
|
foo: Foo
|
578
623
|
bar: Bar
|
579
624
|
foo2: Foo
|
625
|
+
|
626
|
+
def bar_value(self) -> str:
|
627
|
+
return self.bar.y
|
628
|
+
|
629
|
+
def foo_value(self) -> int:
|
630
|
+
return self.foo.x
|
580
631
|
```
|
581
632
|
'''),
|
582
633
|
)
|
@@ -584,16 +635,12 @@ class SchemaPythonReprTest(unittest.TestCase):
|
|
584
635
|
schema_lib.SchemaPythonRepr().repr(
|
585
636
|
schema,
|
586
637
|
include_result_definition=False,
|
587
|
-
include_pg_object_as_base=True,
|
588
638
|
markdown=False,
|
589
639
|
),
|
590
640
|
inspect.cleandoc('''
|
591
|
-
class Foo
|
641
|
+
class Foo:
|
592
642
|
x: int
|
593
643
|
|
594
|
-
class A(Object):
|
595
|
-
foo: Foo
|
596
|
-
|
597
644
|
class Bar:
|
598
645
|
"""Class Bar."""
|
599
646
|
y: str
|
@@ -602,10 +649,16 @@ class SchemaPythonReprTest(unittest.TestCase):
|
|
602
649
|
"""Baz(y: str)"""
|
603
650
|
y: str
|
604
651
|
|
605
|
-
class B
|
652
|
+
class B:
|
606
653
|
foo: Foo
|
607
654
|
bar: Bar
|
608
655
|
foo2: Foo
|
656
|
+
|
657
|
+
def bar_value(self) -> str:
|
658
|
+
return self.bar.y
|
659
|
+
|
660
|
+
def foo_value(self) -> int:
|
661
|
+
return self.foo.x
|
609
662
|
'''),
|
610
663
|
)
|
611
664
|
|
@@ -653,7 +706,7 @@ class ValuePythonReprTest(unittest.TestCase):
|
|
653
706
|
```python
|
654
707
|
class Foo(Object):
|
655
708
|
x: int
|
656
|
-
|
709
|
+
|
657
710
|
class A(Object):
|
658
711
|
foo: list[Foo]
|
659
712
|
y: str | None
|
langfun/core/template_test.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: langfun
|
3
|
-
Version: 0.0.2.
|
3
|
+
Version: 0.0.2.dev20240531
|
4
4
|
Summary: Langfun: Language as Functions.
|
5
5
|
Home-page: https://github.com/google/langfun
|
6
6
|
Author: Langfun Authors
|
@@ -30,6 +30,8 @@ Requires-Dist: python-magic >=0.4.27
|
|
30
30
|
Requires-Dist: requests >=2.31.0
|
31
31
|
Requires-Dist: termcolor ==1.1.0
|
32
32
|
Requires-Dist: tqdm >=4.64.1
|
33
|
+
Requires-Dist: python-docx >=0.8.11
|
34
|
+
Requires-Dist: pandas >=2.1.4
|
33
35
|
|
34
36
|
<div align="center">
|
35
37
|
<img src="https://raw.githubusercontent.com/google/langfun/main/docs/_static/logo.svg" width="520px" alt="logo"></img>
|