langfun 0.1.2.dev202409160804__py3-none-any.whl → 0.1.2.dev202409180804__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/core/__init__.py CHANGED
@@ -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)
langfun/core/logging.py CHANGED
@@ -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
@@ -1,5 +1,5 @@
1
1
  langfun/__init__.py,sha256=mCES7t3R7Z-ZQYvG38-yrVqZubrXNfGCa8tI5HGB7mE,2274
2
- langfun/core/__init__.py,sha256=r86kuy-BiJIveqnXx5OklUUXtMG3q79nWRBum6zFOCQ,4835
2
+ langfun/core/__init__.py,sha256=gKoZrxwxdR_UweutfeeECUEL6ogcr8lKk9ub5_9NaM0,4884
3
3
  langfun/core/component.py,sha256=nxF4UD7NLduPjrf4IAtysMAIg3IChfoQHjY77vC8f_E,10263
4
4
  langfun/core/component_test.py,sha256=q15Xn51cVTu2RKxZ9U5VQgT3bm6RQ4638bKhWBtvW5o,8220
5
5
  langfun/core/concurrent.py,sha256=D_zoLGFREGfm0G93V27wzOlFh3MjaDxUZKb9g6Z69d4,28019
@@ -10,7 +10,7 @@ langfun/core/langfunc.py,sha256=G50YgoVZ0y1GFw2ev41MlOqr6qa8YakbvNC0h_E0PiA,1114
10
10
  langfun/core/langfunc_test.py,sha256=ZLlj6ysNIWUlm0jcq6PbNUwdJ2XstW5QQT0L2s5GlGY,8753
11
11
  langfun/core/language_model.py,sha256=o1MPDdiZ7eRUhcCjxLMT6IYYXge6nM7elvCWQ-NANaU,26286
12
12
  langfun/core/language_model_test.py,sha256=ebJ1vnaxKSKvlwi6v07yHjn91xMiDw2bQ9DBnyVorYw,23303
13
- langfun/core/logging.py,sha256=oDSeqGIQogZJ6xuPTcr9mkmLC2YnLP67UHtTdWbbiVY,4250
13
+ langfun/core/logging.py,sha256=wYDuPuGeS1hyJBzjMQgquyfLw-TUVO-b7H68UA8X-Eg,4279
14
14
  langfun/core/logging_test.py,sha256=poSsNGKi6G9LWOcWnTY0BQjj0BtaQknH-NK6FcQrVT4,2152
15
15
  langfun/core/memory.py,sha256=f-asN1F7Vehgdn_fK84v73GrEUOxRtaW934keutTKjk,2416
16
16
  langfun/core/message.py,sha256=7UOxNMA1Le0ZGkleryqwXcWojZ-l_hku5Sc58BsIOGw,18586
@@ -19,8 +19,8 @@ langfun/core/modality.py,sha256=g9wGx347oVofAJlMu_CpzTMIyTT9DJW8NfO4E-d-oNM,3879
19
19
  langfun/core/modality_test.py,sha256=7SwhixFME2Q1sIXRgJx97EZFiIyC31A9NVr6_nDtFv4,2441
20
20
  langfun/core/natural_language.py,sha256=3ynSnaYQnjE60LIPK5fyMgdIjubnPYZwzGq4rWPeloE,1177
21
21
  langfun/core/natural_language_test.py,sha256=LHGU_1ytbkGuSZQFIFP7vP3dBlcY4-A12fT6dbjUA0E,1424
22
- langfun/core/repr_utils.py,sha256=Y6ccoQUMpRxDv_jUy2QtnP9cdz3QBjJtTIgxGIU-kfM,5537
23
- langfun/core/repr_utils_test.py,sha256=_VhWpDbtlWaGadXL0gpmwQVmACenvzmLUng_AqR6zaE,2685
22
+ langfun/core/repr_utils.py,sha256=S2aZQllHuy2syduFiYKJm--GPoJWRGS5cXvbC1pdEUs,6243
23
+ langfun/core/repr_utils_test.py,sha256=ULG7gvgoyqQFWi0m6g2-E0GorNEr1nnZ0J_sZVQKz80,3036
24
24
  langfun/core/sampling.py,sha256=vygWvgC8MFw0_AKNSmz-ywMXJYWf8cl0tI8QycvAmyI,5795
25
25
  langfun/core/sampling_test.py,sha256=U7PANpMsl9E_pa4_Y4FzesSjcwg-u-LKHGCWSgv-8FY,3663
26
26
  langfun/core/subscription.py,sha256=euawEuSZP-BHydaT-AQpfYFL0m5pWPGcW0upFhrojqc,10930
@@ -46,7 +46,7 @@ langfun/core/coding/python/permissions_test.py,sha256=w5EDb8QxpxgJyZkojyzVWQvDfg
46
46
  langfun/core/eval/__init__.py,sha256=Ogdr9OtTywhhLPHi3AZzOD2mXX2oyaHWflrSTMm96uA,1899
47
47
  langfun/core/eval/base.py,sha256=xDZQ3lu5oJaPDZCE5-QbBEajq--HRU64GVKb3xB64aI,74738
48
48
  langfun/core/eval/base_test.py,sha256=VEraWaRybSxOCOcZrZouNkiroDEPR6uyFBJoAz-1pQg,26930
49
- langfun/core/eval/matching.py,sha256=foqHIfEbmgWMfGv3ia0bCsf6m6PTr_Oeb8FZobbyud8,9900
49
+ langfun/core/eval/matching.py,sha256=vjA7g413kAV7VASwNIVUayMhhXvtjttY0nr3UdHqXwk,10132
50
50
  langfun/core/eval/matching_test.py,sha256=f7iVyXH5KGJBWt4Wp14Bt9J3X59A6Ayfog9MbuFvPew,5532
51
51
  langfun/core/eval/patching.py,sha256=R0s2eAd1m97exQt06dmUL0V_MBG0W2Hxg7fhNB7cXW0,3866
52
52
  langfun/core/eval/patching_test.py,sha256=8kCd54Egjju22FMgtJuxEsrXkW8ifs-UUBHtrCG1L6w,4775
@@ -119,8 +119,8 @@ langfun/core/templates/demonstration.py,sha256=vCrgYubdZM5Umqcgp8NUVGXgr4P_c-fik
119
119
  langfun/core/templates/demonstration_test.py,sha256=SafcDQ0WgI7pw05EmPI2S4v1t3ABKzup8jReCljHeK4,2162
120
120
  langfun/core/templates/selfplay.py,sha256=yhgrJbiYwq47TgzThmHrDQTF4nDrTI09CWGhuQPNv-s,2273
121
121
  langfun/core/templates/selfplay_test.py,sha256=rBW2Qr8yi-aWYwoTwRR-n1peKyMX9QXPZXURjLgoiRs,2264
122
- langfun-0.1.2.dev202409160804.dist-info/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
123
- langfun-0.1.2.dev202409160804.dist-info/METADATA,sha256=Hoxy-A9HeoH_XYYSkiN0-MLqo9nL45Occt12WEcMmK0,8890
124
- langfun-0.1.2.dev202409160804.dist-info/WHEEL,sha256=5Mi1sN9lKoFv_gxcPtisEVrJZihrm_beibeg5R6xb4I,91
125
- langfun-0.1.2.dev202409160804.dist-info/top_level.txt,sha256=RhlEkHxs1qtzmmtWSwYoLVJAc1YrbPtxQ52uh8Z9VvY,8
126
- langfun-0.1.2.dev202409160804.dist-info/RECORD,,
122
+ langfun-0.1.2.dev202409180804.dist-info/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
123
+ langfun-0.1.2.dev202409180804.dist-info/METADATA,sha256=8r43i6FzNi9hKws1cufJ5ZdtRHDWuyRiDZ7UniEq8gE,8890
124
+ langfun-0.1.2.dev202409180804.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
125
+ langfun-0.1.2.dev202409180804.dist-info/top_level.txt,sha256=RhlEkHxs1qtzmmtWSwYoLVJAc1YrbPtxQ52uh8Z9VvY,8
126
+ langfun-0.1.2.dev202409180804.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.0.0)
2
+ Generator: setuptools (75.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5