langfun 0.1.2.dev202409160804__tar.gz → 0.1.2.dev202409180804__tar.gz

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.
Files changed (131) hide show
  1. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/PKG-INFO +1 -1
  2. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/__init__.py +1 -0
  3. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/eval/matching.py +12 -2
  4. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/logging.py +13 -7
  5. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/repr_utils.py +53 -30
  6. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/repr_utils_test.py +17 -2
  7. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun.egg-info/PKG-INFO +1 -1
  8. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/LICENSE +0 -0
  9. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/README.md +0 -0
  10. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/__init__.py +0 -0
  11. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/coding/__init__.py +0 -0
  12. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/coding/python/__init__.py +0 -0
  13. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/coding/python/correction.py +0 -0
  14. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/coding/python/correction_test.py +0 -0
  15. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/coding/python/errors.py +0 -0
  16. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/coding/python/errors_test.py +0 -0
  17. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/coding/python/execution.py +0 -0
  18. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/coding/python/execution_test.py +0 -0
  19. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/coding/python/generation.py +0 -0
  20. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/coding/python/generation_test.py +0 -0
  21. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/coding/python/parsing.py +0 -0
  22. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/coding/python/parsing_test.py +0 -0
  23. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/coding/python/permissions.py +0 -0
  24. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/coding/python/permissions_test.py +0 -0
  25. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/component.py +0 -0
  26. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/component_test.py +0 -0
  27. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/concurrent.py +0 -0
  28. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/concurrent_test.py +0 -0
  29. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/console.py +0 -0
  30. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/console_test.py +0 -0
  31. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/eval/__init__.py +0 -0
  32. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/eval/base.py +0 -0
  33. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/eval/base_test.py +0 -0
  34. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/eval/matching_test.py +0 -0
  35. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/eval/patching.py +0 -0
  36. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/eval/patching_test.py +0 -0
  37. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/eval/scoring.py +0 -0
  38. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/eval/scoring_test.py +0 -0
  39. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/langfunc.py +0 -0
  40. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/langfunc_test.py +0 -0
  41. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/language_model.py +0 -0
  42. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/language_model_test.py +0 -0
  43. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/llms/__init__.py +0 -0
  44. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/llms/anthropic.py +0 -0
  45. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/llms/anthropic_test.py +0 -0
  46. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/llms/cache/__init__.py +0 -0
  47. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/llms/cache/base.py +0 -0
  48. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/llms/cache/in_memory.py +0 -0
  49. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/llms/cache/in_memory_test.py +0 -0
  50. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/llms/fake.py +0 -0
  51. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/llms/fake_test.py +0 -0
  52. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/llms/google_genai.py +0 -0
  53. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/llms/google_genai_test.py +0 -0
  54. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/llms/groq.py +0 -0
  55. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/llms/groq_test.py +0 -0
  56. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/llms/llama_cpp.py +0 -0
  57. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/llms/llama_cpp_test.py +0 -0
  58. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/llms/openai.py +0 -0
  59. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/llms/openai_test.py +0 -0
  60. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/llms/rest.py +0 -0
  61. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/llms/rest_test.py +0 -0
  62. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/llms/vertexai.py +0 -0
  63. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/llms/vertexai_test.py +0 -0
  64. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/logging_test.py +0 -0
  65. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/memories/__init__.py +0 -0
  66. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/memories/conversation_history.py +0 -0
  67. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/memories/conversation_history_test.py +0 -0
  68. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/memory.py +0 -0
  69. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/message.py +0 -0
  70. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/message_test.py +0 -0
  71. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/modalities/__init__.py +0 -0
  72. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/modalities/audio.py +0 -0
  73. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/modalities/audio_test.py +0 -0
  74. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/modalities/image.py +0 -0
  75. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/modalities/image_test.py +0 -0
  76. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/modalities/mime.py +0 -0
  77. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/modalities/mime_test.py +0 -0
  78. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/modalities/ms_office.py +0 -0
  79. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/modalities/ms_office_test.py +0 -0
  80. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/modalities/pdf.py +0 -0
  81. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/modalities/pdf_test.py +0 -0
  82. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/modalities/video.py +0 -0
  83. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/modalities/video_test.py +0 -0
  84. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/modality.py +0 -0
  85. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/modality_test.py +0 -0
  86. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/natural_language.py +0 -0
  87. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/natural_language_test.py +0 -0
  88. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/sampling.py +0 -0
  89. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/sampling_test.py +0 -0
  90. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/structured/__init__.py +0 -0
  91. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/structured/completion.py +0 -0
  92. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/structured/completion_test.py +0 -0
  93. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/structured/description.py +0 -0
  94. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/structured/description_test.py +0 -0
  95. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/structured/function_generation.py +0 -0
  96. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/structured/function_generation_test.py +0 -0
  97. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/structured/mapping.py +0 -0
  98. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/structured/mapping_test.py +0 -0
  99. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/structured/parsing.py +0 -0
  100. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/structured/parsing_test.py +0 -0
  101. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/structured/prompting.py +0 -0
  102. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/structured/prompting_test.py +0 -0
  103. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/structured/schema.py +0 -0
  104. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/structured/schema_generation.py +0 -0
  105. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/structured/schema_generation_test.py +0 -0
  106. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/structured/schema_test.py +0 -0
  107. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/structured/scoring.py +0 -0
  108. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/structured/scoring_test.py +0 -0
  109. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/structured/tokenization.py +0 -0
  110. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/structured/tokenization_test.py +0 -0
  111. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/subscription.py +0 -0
  112. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/subscription_test.py +0 -0
  113. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/template.py +0 -0
  114. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/template_test.py +0 -0
  115. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/templates/__init__.py +0 -0
  116. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/templates/completion.py +0 -0
  117. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/templates/completion_test.py +0 -0
  118. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/templates/conversation.py +0 -0
  119. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/templates/conversation_test.py +0 -0
  120. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/templates/demonstration.py +0 -0
  121. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/templates/demonstration_test.py +0 -0
  122. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/templates/selfplay.py +0 -0
  123. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/templates/selfplay_test.py +0 -0
  124. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/text_formatting.py +0 -0
  125. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun/core/text_formatting_test.py +0 -0
  126. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun.egg-info/SOURCES.txt +0 -0
  127. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun.egg-info/dependency_links.txt +0 -0
  128. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun.egg-info/requires.txt +0 -0
  129. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/langfun.egg-info/top_level.txt +0 -0
  130. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/setup.cfg +0 -0
  131. {langfun-0.1.2.dev202409160804 → langfun-0.1.2.dev202409180804}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: langfun
3
- Version: 0.1.2.dev202409160804
3
+ Version: 0.1.2.dev202409180804
4
4
  Summary: Langfun: Language as Functions.
5
5
  Home-page: https://github.com/google/langfun
6
6
  Author: Langfun Authors
@@ -45,6 +45,7 @@ use_context = context
45
45
  from langfun.core.component import use_settings
46
46
 
47
47
  from langfun.core.component import get_contextual_override
48
+ from langfun.core.component import context_value
48
49
 
49
50
  # Value marker for attribute whose values will be provided from parent
50
51
  # objects or from the `pg.component_context` context manager.
@@ -275,9 +275,19 @@ class Matching(base.Evaluation):
275
275
  for i, (example, output, message) in enumerate(self.matches):
276
276
  bgcolor = 'white' if i % 2 == 0 else '#DDDDDD'
277
277
  s.write(f'<tr style="background-color: {bgcolor}"><td>{i + 1}</td>')
278
- input_str = pg.format(example, verbose=False, max_bytes_len=32)
278
+ input_str = lf.repr_utils.escape_quoted(
279
+ pg.format(
280
+ example, verbose=False, max_bytes_len=32,
281
+ custom_format='_repr_html_'
282
+ )
283
+ )
279
284
  s.write(f'<td style="color:green;white-space:pre-wrap">{input_str}</td>')
280
- output_str = pg.format(output, verbose=False, max_bytes_len=32)
285
+ output_str = lf.repr_utils.escape_quoted(
286
+ pg.format(
287
+ output, verbose=False, max_bytes_len=32,
288
+ custom_format='_repr_html_'
289
+ )
290
+ )
281
291
  s.write(f'<td style="color:blue;white-space:pre-wrap">{output_str}</td>')
282
292
  s.write('<td>')
283
293
  self._render_message(message, s)
@@ -13,11 +13,14 @@
13
13
  # limitations under the License.
14
14
  """Langfun event logging."""
15
15
 
16
+ from collections.abc import Iterator
17
+ import contextlib
16
18
  import datetime
17
19
  import io
18
20
  import typing
19
- from typing import Any, Literal, ContextManager
21
+ from typing import Any, Literal
20
22
 
23
+ from langfun.core import component
21
24
  from langfun.core import console
22
25
  from langfun.core import repr_utils
23
26
  import pyglove as pg
@@ -25,18 +28,21 @@ import pyglove as pg
25
28
 
26
29
  LogLevel = Literal['debug', 'info', 'error', 'warning', 'fatal']
27
30
  _LOG_LEVELS = list(typing.get_args(LogLevel))
28
- _TLS_KEY_MIN_LOG_LEVEL = '_event_log_level'
29
31
 
30
32
 
31
- def use_log_level(log_level: LogLevel | None = 'info') -> ContextManager[None]:
33
+ @contextlib.contextmanager
34
+ def use_log_level(log_level: LogLevel = 'info') -> Iterator[None]:
32
35
  """Contextmanager to enable logging at a given level."""
33
- return pg.object_utils.thread_local_value_scope(
34
- _TLS_KEY_MIN_LOG_LEVEL, log_level, 'info')
36
+ with component.context(__event_log_level__=log_level):
37
+ try:
38
+ yield
39
+ finally:
40
+ pass
35
41
 
36
42
 
37
- def get_log_level() -> LogLevel | None:
43
+ def get_log_level() -> LogLevel:
38
44
  """Gets the current minimum log level."""
39
- return pg.object_utils.thread_local_get(_TLS_KEY_MIN_LOG_LEVEL, 'info')
45
+ return component.context_value('__event_log_level__', 'info')
40
46
 
41
47
 
42
48
  class LogEntry(pg.Object):
@@ -94,7 +94,7 @@ def write_maybe_shared(s: io.StringIO, content: str) -> bool:
94
94
 
95
95
 
96
96
  def html_repr(
97
- value: Any,
97
+ value: dict[str, Any],
98
98
  item_color: Callable[
99
99
  [str, str],
100
100
  tuple[
@@ -121,35 +121,38 @@ def html_repr(
121
121
  s.write('<table style="border-top: 1px solid #EEEEEE;">')
122
122
  item_color = item_color or (lambda k, v: (None, '#F1C40F', None, None))
123
123
 
124
- for k, v in pg.object_utils.flatten(value).items():
125
- if isinstance(v, pg.Ref):
126
- v = v.value
127
- if hasattr(v, '_repr_html_'):
128
- cs = v._repr_html_() # pylint: disable=protected-access
129
- else:
130
- cs = f'<span style="white-space: pre-wrap">{html.escape(str(v))}</span>'
131
-
132
- key_color, key_bg_color, value_color, value_bg_color = item_color(k, v)
133
- key_span = html_round_text(
134
- k,
135
- text_color=key_color,
136
- background_color=key_bg_color,
137
- margin_bottom='0px'
138
- )
139
- value_color_style = f'color: {value_color};' if value_color else ''
140
- value_bg_color_style = (
141
- f'background-color: {value_bg_color};' if value_bg_color else ''
142
- )
143
- s.write(
144
- '<tr>'
145
- '<td style="padding: 5px; vertical-align: top; '
146
- f'border-bottom: 1px solid #EEEEEE">{key_span}</td>'
147
- '<td style="padding: 15px 5px 5px 5px; vertical-align: top; '
148
- 'border-bottom: 1px solid #EEEEEE;'
149
- f'{value_color_style}{value_bg_color_style}">{cs}</td></tr>'
150
- )
151
- s.write('</table></div>')
152
- return s.getvalue()
124
+ with (pg.str_format(custom_format='_repr_html_'),
125
+ pg.repr_format(custom_format='_repr_html_')):
126
+ for k, v in pg.object_utils.flatten(value).items():
127
+ if isinstance(v, pg.Ref):
128
+ v = v.value
129
+ if hasattr(v, '_repr_html_'):
130
+ cs = v._repr_html_() # pylint: disable=protected-access
131
+ else:
132
+ cs = html.escape(v) if isinstance(v, str) else escape_quoted(str(v))
133
+ cs = f'<span style="white-space: pre-wrap">{cs}</span>'
134
+
135
+ key_color, key_bg_color, value_color, value_bg_color = item_color(k, v)
136
+ key_span = html_round_text(
137
+ k,
138
+ text_color=key_color,
139
+ background_color=key_bg_color,
140
+ margin_bottom='0px'
141
+ )
142
+ value_color_style = f'color: {value_color};' if value_color else ''
143
+ value_bg_color_style = (
144
+ f'background-color: {value_bg_color};' if value_bg_color else ''
145
+ )
146
+ s.write(
147
+ '<tr>'
148
+ '<td style="padding: 5px; vertical-align: top; '
149
+ f'border-bottom: 1px solid #EEEEEE">{key_span}</td>'
150
+ '<td style="padding: 15px 5px 5px 5px; vertical-align: top; '
151
+ 'border-bottom: 1px solid #EEEEEE;'
152
+ f'{value_color_style}{value_bg_color_style}">{cs}</td></tr>'
153
+ )
154
+ s.write('</table></div>')
155
+ return s.getvalue()
153
156
 
154
157
 
155
158
  def html_round_text(
@@ -172,3 +175,23 @@ def html_round_text(
172
175
  f'margin-top: {margin_top}; margin-bottom: {margin_bottom}; '
173
176
  f'white-space: {whitespace}">{text}</span>'
174
177
  )
178
+
179
+
180
+ def escape_quoted(s: str):
181
+ """Escape quoted parts within a string."""
182
+ r = io.StringIO()
183
+ quote_char = None
184
+ quote_start = -1
185
+ for i, c in enumerate(s):
186
+ if c in ('\'', '"'):
187
+ if quote_char is None:
188
+ quote_char = c
189
+ quote_start = i
190
+ elif quote_char == c:
191
+ r.write(c)
192
+ r.write(html.escape(s[quote_start + 1:i]))
193
+ r.write(c)
194
+ quote_char = None
195
+ elif quote_char is None:
196
+ r.write(c)
197
+ return r.getvalue()
@@ -54,6 +54,15 @@ class SharingContentTest(unittest.TestCase):
54
54
  self.assertEqual(ctx1['<style>b</style>'], 2)
55
55
  self.assertEqual(ctx1['<style>a</style>'], 4)
56
56
 
57
+ def test_escape_quoted(self):
58
+ self.assertEqual(
59
+ repr_utils.escape_quoted(str('<a>')), '<a>'
60
+ )
61
+ self.assertEqual(
62
+ repr_utils.escape_quoted('x=<a>, b="<a>"'),
63
+ 'x=<a>, b="&lt;a&gt;"'
64
+ )
65
+
57
66
  def test_html(self):
58
67
  html = repr_utils.Html('<div>foo</div>')
59
68
  self.assertEqual(html.content, '<div>foo</div>')
@@ -63,12 +72,18 @@ class SharingContentTest(unittest.TestCase):
63
72
  class Foo(pg.Object):
64
73
  x: int
65
74
 
75
+ class Bar(pg.Object):
76
+
77
+ def _repr_html_(self):
78
+ return '<bar>'
79
+
66
80
  html = repr_utils.html_repr(
67
- {'foo': pg.Ref(Foo(1)), 'bar': '<lf_image>'}
81
+ {'foo': pg.Ref(Foo(1)), 'bar': Bar(), 'baz': '<lf_image>'}
68
82
  )
69
83
  self.assertIn('foo</span>', html)
70
- self.assertNotIn('Ref', html)
84
+ self.assertIn('<bar>', html)
71
85
  self.assertIn('&lt;lf_image&gt;', html)
86
+ self.assertNotIn('Ref', html)
72
87
 
73
88
 
74
89
  if __name__ == '__main__':
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: langfun
3
- Version: 0.1.2.dev202409160804
3
+ Version: 0.1.2.dev202409180804
4
4
  Summary: Langfun: Language as Functions.
5
5
  Home-page: https://github.com/google/langfun
6
6
  Author: Langfun Authors