pyglove 0.4.5.dev202505150810__py3-none-any.whl → 0.4.5.dev202505160810__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/symbolic/__init__.py +1 -0
- pyglove/core/symbolic/error_info.py +127 -0
- pyglove/core/symbolic/error_info_test.py +92 -0
- pyglove/core/symbolic/object.py +17 -2
- pyglove/core/symbolic/object_test.py +28 -0
- pyglove/core/utils/error_utils.py +22 -40
- pyglove/core/utils/error_utils_test.py +0 -56
- pyglove/core/utils/text_color_test.py +5 -2
- pyglove/core/utils/timing_test.py +1 -0
- {pyglove-0.4.5.dev202505150810.dist-info → pyglove-0.4.5.dev202505160810.dist-info}/METADATA +1 -1
- {pyglove-0.4.5.dev202505150810.dist-info → pyglove-0.4.5.dev202505160810.dist-info}/RECORD +14 -12
- {pyglove-0.4.5.dev202505150810.dist-info → pyglove-0.4.5.dev202505160810.dist-info}/WHEEL +0 -0
- {pyglove-0.4.5.dev202505150810.dist-info → pyglove-0.4.5.dev202505160810.dist-info}/licenses/LICENSE +0 -0
- {pyglove-0.4.5.dev202505150810.dist-info → pyglove-0.4.5.dev202505160810.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,127 @@
|
|
1
|
+
# Copyright 2025 The PyGlove Authors
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
"""Symbolic class for capture error information."""
|
15
|
+
|
16
|
+
from typing import Annotated, List
|
17
|
+
from pyglove.core import utils
|
18
|
+
from pyglove.core.symbolic import dict as pg_dict # pylint: disable=unused-import
|
19
|
+
from pyglove.core.symbolic import list as pg_list # pylint: disable=unused-import
|
20
|
+
from pyglove.core.symbolic import object as pg_object
|
21
|
+
from pyglove.core.views.html import controls
|
22
|
+
from pyglove.core.views.html import tree_view
|
23
|
+
|
24
|
+
|
25
|
+
@pg_object.members(
|
26
|
+
[],
|
27
|
+
# For backwards compatibility.
|
28
|
+
additional_keys=['pyglove.core.utils.error_utils.ErrorInfo']
|
29
|
+
)
|
30
|
+
class ErrorInfo(
|
31
|
+
pg_object.Object,
|
32
|
+
utils.ErrorInfo,
|
33
|
+
tree_view.HtmlTreeView.Extension
|
34
|
+
):
|
35
|
+
"""Symbolic error info."""
|
36
|
+
|
37
|
+
tag: Annotated[
|
38
|
+
str,
|
39
|
+
(
|
40
|
+
'A path of the error types in the exception chain. For example, '
|
41
|
+
'`ValueError.ZeroDivisionError` means the error is a '
|
42
|
+
'`ZeroDivisionError` raised at the first place and then reraised as '
|
43
|
+
'a `ValueError`.'
|
44
|
+
)
|
45
|
+
]
|
46
|
+
|
47
|
+
description: Annotated[
|
48
|
+
str,
|
49
|
+
'The description of the error.',
|
50
|
+
]
|
51
|
+
|
52
|
+
stacktrace: Annotated[
|
53
|
+
str,
|
54
|
+
'The stacktrace of the error.',
|
55
|
+
]
|
56
|
+
|
57
|
+
def _html_tree_view_summary(
|
58
|
+
self,
|
59
|
+
*,
|
60
|
+
view: tree_view.HtmlTreeView,
|
61
|
+
**kwargs
|
62
|
+
) -> tree_view.Html:
|
63
|
+
kwargs.pop('title', None)
|
64
|
+
kwargs.pop('enable_summary_tooltip', None)
|
65
|
+
return view.summary(
|
66
|
+
self,
|
67
|
+
title=tree_view.Html.element(
|
68
|
+
'div',
|
69
|
+
[
|
70
|
+
'ErrorInfo',
|
71
|
+
controls.Label(self.tag, css_classes=['error_tag']),
|
72
|
+
],
|
73
|
+
styles=dict(display='inline-block')
|
74
|
+
),
|
75
|
+
enable_summary_tooltip=False,
|
76
|
+
**kwargs
|
77
|
+
)
|
78
|
+
|
79
|
+
def _html_tree_view_content(self, **kwargs) -> tree_view.Html:
|
80
|
+
del kwargs
|
81
|
+
return controls.TabControl([
|
82
|
+
controls.Tab(
|
83
|
+
'description',
|
84
|
+
tree_view.Html.element(
|
85
|
+
'div',
|
86
|
+
[
|
87
|
+
tree_view.Html.escape(utils.decolor(self.description))
|
88
|
+
],
|
89
|
+
css_classes=['error_text']
|
90
|
+
)
|
91
|
+
),
|
92
|
+
controls.Tab(
|
93
|
+
'stacktrace',
|
94
|
+
tree_view.Html.element(
|
95
|
+
'div',
|
96
|
+
[
|
97
|
+
tree_view.Html.escape(utils.decolor(self.stacktrace))
|
98
|
+
],
|
99
|
+
css_classes=['error_text']
|
100
|
+
)
|
101
|
+
)
|
102
|
+
]).to_html()
|
103
|
+
|
104
|
+
@classmethod
|
105
|
+
def _html_tree_view_css_styles(cls) -> List[str]:
|
106
|
+
return super()._html_tree_view_css_styles() + [
|
107
|
+
'''
|
108
|
+
.error_tag {
|
109
|
+
background-color: red;
|
110
|
+
border-radius: 5px;
|
111
|
+
padding: 5px;
|
112
|
+
margin-left: 5px;
|
113
|
+
color: white;
|
114
|
+
font-size: small;
|
115
|
+
}
|
116
|
+
.error_text {
|
117
|
+
display: block;
|
118
|
+
white-space: pre-wrap;
|
119
|
+
padding: 0.5em;
|
120
|
+
margin-top: 0.15em;
|
121
|
+
background-color: #f2f2f2;
|
122
|
+
}
|
123
|
+
'''
|
124
|
+
]
|
125
|
+
|
126
|
+
# Use the symbolic error info class as the default ErrorInfo implementation.
|
127
|
+
utils.ErrorInfo._IMPLEMENTATION = ErrorInfo # pylint: disable=protected-access
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# Copyright 2025 The PyGlove Authors
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
import inspect
|
16
|
+
import unittest
|
17
|
+
from pyglove.core.symbolic import base
|
18
|
+
from pyglove.core.symbolic import error_info as error_info_lib # pylint: disable=g-bad-import-order
|
19
|
+
|
20
|
+
|
21
|
+
class ErrorInfoTest(unittest.TestCase):
|
22
|
+
"""Tests for ErrorInfo."""
|
23
|
+
|
24
|
+
def test_from_exception(self):
|
25
|
+
|
26
|
+
def foo():
|
27
|
+
return 1 / 0
|
28
|
+
|
29
|
+
def bar():
|
30
|
+
try:
|
31
|
+
foo()
|
32
|
+
except ZeroDivisionError as e:
|
33
|
+
raise ValueError('Bad call to `foo`') from e
|
34
|
+
|
35
|
+
error_info = None
|
36
|
+
try:
|
37
|
+
bar()
|
38
|
+
except ValueError as e:
|
39
|
+
error_info = error_info_lib.ErrorInfo.from_exception(e)
|
40
|
+
self.assertIsNotNone(error_info)
|
41
|
+
self.assertEqual(error_info.tag, 'ValueError.ZeroDivisionError')
|
42
|
+
self.assertEqual(error_info.description, 'Bad call to `foo`')
|
43
|
+
self.assertIn('Traceback (most recent call last)', error_info.stacktrace)
|
44
|
+
|
45
|
+
def test_to_json(self):
|
46
|
+
error_info = error_info_lib.ErrorInfo(
|
47
|
+
tag='ValueError.ZeroDivisionError',
|
48
|
+
description='Bad call to `foo`',
|
49
|
+
stacktrace='Traceback (most recent call last)',
|
50
|
+
)
|
51
|
+
json_dict = error_info.to_json()
|
52
|
+
error_info2 = base.from_json(json_dict)
|
53
|
+
self.assertIsNot(error_info2, error_info)
|
54
|
+
self.assertEqual(error_info2, error_info)
|
55
|
+
json_dict['_type'] = 'pyglove.core.utils.error_utils.ErrorInfo'
|
56
|
+
error_info2 = base.from_json(json_dict)
|
57
|
+
self.assertEqual(error_info2, error_info)
|
58
|
+
|
59
|
+
def test_format(self):
|
60
|
+
error_info = error_info_lib.ErrorInfo(
|
61
|
+
tag='ValueError.ZeroDivisionError',
|
62
|
+
description='Bad call to `foo`',
|
63
|
+
stacktrace='Traceback (most recent call last)',
|
64
|
+
)
|
65
|
+
self.assertEqual(
|
66
|
+
error_info.format(compact=False),
|
67
|
+
inspect.cleandoc(
|
68
|
+
"""
|
69
|
+
ErrorInfo(
|
70
|
+
tag = 'ValueError.ZeroDivisionError',
|
71
|
+
description = 'Bad call to `foo`',
|
72
|
+
stacktrace = 'Traceback (most recent call last)'
|
73
|
+
)
|
74
|
+
"""
|
75
|
+
)
|
76
|
+
)
|
77
|
+
|
78
|
+
def test_to_html(self):
|
79
|
+
error_info = error_info_lib.ErrorInfo(
|
80
|
+
tag='ValueError.ZeroDivisionError',
|
81
|
+
description='Bad call to `foo`',
|
82
|
+
stacktrace='Traceback (most recent call last)',
|
83
|
+
)
|
84
|
+
html = error_info.to_html()
|
85
|
+
self.assertIn('ErrorInfo', html.content)
|
86
|
+
self.assertIn('ValueError.ZeroDivisionError', html.content)
|
87
|
+
self.assertIn('Bad call to `foo`', html.content)
|
88
|
+
self.assertIn('Traceback (most recent call last)', html.content)
|
89
|
+
|
90
|
+
|
91
|
+
if __name__ == '__main__':
|
92
|
+
unittest.main()
|
pyglove/core/symbolic/object.py
CHANGED
@@ -101,6 +101,18 @@ class ObjectMeta(abc.ABCMeta):
|
|
101
101
|
)
|
102
102
|
cls.apply_schema(schema)
|
103
103
|
|
104
|
+
# Update abstract methods.
|
105
|
+
# abc.update_abstractmethods is only available in Python 3.10 and above.
|
106
|
+
if sys.version_info >= (3, 10):
|
107
|
+
abc.update_abstractmethods(cls)
|
108
|
+
elif cls.allow_symbolic_attribute:
|
109
|
+
abstract_methods = getattr(cls, '__abstractmethods__', frozenset())
|
110
|
+
new_abstract_methods = []
|
111
|
+
for name in abstract_methods:
|
112
|
+
if name not in cls.__schema__.fields:
|
113
|
+
new_abstract_methods.append(name)
|
114
|
+
setattr(cls, '__abstractmethods__', frozenset(new_abstract_methods))
|
115
|
+
|
104
116
|
def register_for_deserialization(
|
105
117
|
cls,
|
106
118
|
serialization_key: Optional[str] = None,
|
@@ -506,7 +518,10 @@ class Object(base.Symbolic, metaclass=ObjectMeta):
|
|
506
518
|
attr_value = getattr(cls, attr_name, pg_typing.MISSING_VALUE)
|
507
519
|
if attr_value == pg_typing.MISSING_VALUE or (
|
508
520
|
not inspect.isfunction(attr_value)
|
509
|
-
and
|
521
|
+
and (
|
522
|
+
not isinstance(attr_value, property)
|
523
|
+
or getattr(attr_value, '__isabstractmethod__', False)
|
524
|
+
)
|
510
525
|
):
|
511
526
|
setattr(cls, attr_name, cls._create_sym_attribute(attr_name, field))
|
512
527
|
|
@@ -517,7 +532,7 @@ class Object(base.Symbolic, metaclass=ObjectMeta):
|
|
517
532
|
coding.make_function(
|
518
533
|
attr_name,
|
519
534
|
['self'],
|
520
|
-
[f
|
535
|
+
[f'return self.sym_inferred(\'{attr_name}\')'],
|
521
536
|
return_type=field.value.annotation,
|
522
537
|
)
|
523
538
|
)
|
@@ -11,6 +11,7 @@
|
|
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
|
+
import abc
|
14
15
|
import copy
|
15
16
|
import inspect
|
16
17
|
import io
|
@@ -493,6 +494,33 @@ class ObjectTest(unittest.TestCase):
|
|
493
494
|
self.assertEqual(b.x, 2)
|
494
495
|
self.assertEqual(b.sym_init_args.x, 1)
|
495
496
|
|
497
|
+
def test_override_abstract_property(self):
|
498
|
+
class A(metaclass=abc.ABCMeta):
|
499
|
+
|
500
|
+
@property
|
501
|
+
@abc.abstractmethod
|
502
|
+
def x(self):
|
503
|
+
pass
|
504
|
+
|
505
|
+
class B(Object, A):
|
506
|
+
x: int
|
507
|
+
|
508
|
+
self.assertEqual(B(1).x, 1)
|
509
|
+
|
510
|
+
def test_override_abstract_property_with_members_decorator(self):
|
511
|
+
class A(metaclass=abc.ABCMeta):
|
512
|
+
|
513
|
+
@property
|
514
|
+
@abc.abstractmethod
|
515
|
+
def x(self):
|
516
|
+
pass
|
517
|
+
|
518
|
+
class B(Object, A):
|
519
|
+
pass
|
520
|
+
|
521
|
+
pg_members([('x', pg_typing.Int())])(B)
|
522
|
+
self.assertEqual(B(1).x, 1) # pylint: disable=abstract-class-instantiated
|
523
|
+
|
496
524
|
def test_runtime_type_check(self):
|
497
525
|
|
498
526
|
@pg_members([
|
@@ -13,33 +13,37 @@
|
|
13
13
|
# limitations under the License.
|
14
14
|
"""Utilities for working with errors."""
|
15
15
|
|
16
|
+
import abc
|
16
17
|
import contextlib
|
17
18
|
import dataclasses
|
18
19
|
import inspect
|
19
20
|
import re
|
20
21
|
import sys
|
21
22
|
import traceback
|
22
|
-
from typing import
|
23
|
+
from typing import Callable, Dict, List, Optional, Sequence, Tuple, Type, Union
|
23
24
|
|
24
|
-
from pyglove.core.utils import formatting
|
25
|
-
from pyglove.core.utils import json_conversion
|
26
25
|
|
26
|
+
class ErrorInfo(metaclass=abc.ABCMeta):
|
27
|
+
"""Interface for error information."""
|
27
28
|
|
28
|
-
|
29
|
-
|
30
|
-
|
29
|
+
# The implementation of ErrorInfo will be a symbolic class, which is
|
30
|
+
# defined in pyglove.core.symbolic.error_info and will be assigned later.
|
31
|
+
_IMPLEMENTATION = None
|
31
32
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
33
|
+
@property
|
34
|
+
@abc.abstractmethod
|
35
|
+
def tag(self) -> str:
|
36
|
+
"""A path of the error types in the exception chain."""
|
37
|
+
|
38
|
+
@property
|
39
|
+
@abc.abstractmethod
|
40
|
+
def description(self) -> str:
|
41
|
+
"""The description of the error."""
|
39
42
|
|
40
|
-
|
41
|
-
|
42
|
-
stacktrace
|
43
|
+
@property
|
44
|
+
@abc.abstractmethod
|
45
|
+
def stacktrace(self) -> str:
|
46
|
+
"""The stacktrace of the error."""
|
43
47
|
|
44
48
|
@classmethod
|
45
49
|
def _compute_tag(cls, error: BaseException):
|
@@ -52,7 +56,8 @@ class ErrorInfo(json_conversion.JSONConvertible, formatting.Formattable):
|
|
52
56
|
@classmethod
|
53
57
|
def from_exception(cls, error: BaseException) -> 'ErrorInfo':
|
54
58
|
"""Creates an error info from an exception."""
|
55
|
-
|
59
|
+
assert cls._IMPLEMENTATION is not None, 'ErrorInfo is not implemented.'
|
60
|
+
return cls._IMPLEMENTATION( # pytype: disable=wrong-arg-types
|
56
61
|
tag=cls._compute_tag(error),
|
57
62
|
description=str(error),
|
58
63
|
stacktrace=''.join(
|
@@ -60,29 +65,6 @@ class ErrorInfo(json_conversion.JSONConvertible, formatting.Formattable):
|
|
60
65
|
)
|
61
66
|
)
|
62
67
|
|
63
|
-
def to_json(self, **kwargs) -> Dict[str, Any]:
|
64
|
-
return self.to_json_dict(
|
65
|
-
fields=dict(
|
66
|
-
tag=(self.tag, None),
|
67
|
-
description=(self.description, None),
|
68
|
-
stacktrace=(self.stacktrace, None),
|
69
|
-
),
|
70
|
-
exclude_default=True,
|
71
|
-
**kwargs,
|
72
|
-
)
|
73
|
-
|
74
|
-
def format(self, *args, **kwargs) -> str:
|
75
|
-
return formatting.kvlist_str(
|
76
|
-
[
|
77
|
-
('tag', self.tag, None),
|
78
|
-
('description', self.description, None),
|
79
|
-
('stacktrace', self.stacktrace, None),
|
80
|
-
],
|
81
|
-
*args,
|
82
|
-
label=self.__class__.__name__,
|
83
|
-
**kwargs,
|
84
|
-
)
|
85
|
-
|
86
68
|
|
87
69
|
@dataclasses.dataclass()
|
88
70
|
class CatchErrorsContext:
|
@@ -11,66 +11,10 @@
|
|
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
|
-
import inspect
|
15
14
|
import unittest
|
16
15
|
from pyglove.core.utils import error_utils
|
17
16
|
|
18
17
|
|
19
|
-
class ErrorInfoTest(unittest.TestCase):
|
20
|
-
"""Tests for ErrorInfo."""
|
21
|
-
|
22
|
-
def test_from_exception(self):
|
23
|
-
|
24
|
-
def foo():
|
25
|
-
return 1 / 0
|
26
|
-
|
27
|
-
def bar():
|
28
|
-
try:
|
29
|
-
foo()
|
30
|
-
except ZeroDivisionError as e:
|
31
|
-
raise ValueError('Bad call to `foo`') from e
|
32
|
-
|
33
|
-
error_info = None
|
34
|
-
try:
|
35
|
-
bar()
|
36
|
-
except ValueError as e:
|
37
|
-
error_info = error_utils.ErrorInfo.from_exception(e)
|
38
|
-
self.assertIsNotNone(error_info)
|
39
|
-
self.assertEqual(error_info.tag, 'ValueError.ZeroDivisionError')
|
40
|
-
self.assertEqual(error_info.description, 'Bad call to `foo`')
|
41
|
-
self.assertIn('Traceback (most recent call last)', error_info.stacktrace)
|
42
|
-
|
43
|
-
def test_to_json(self):
|
44
|
-
error_info = error_utils.ErrorInfo(
|
45
|
-
tag='ValueError.ZeroDivisionError',
|
46
|
-
description='Bad call to `foo`',
|
47
|
-
stacktrace='Traceback (most recent call last)',
|
48
|
-
)
|
49
|
-
json_dict = error_info.to_json()
|
50
|
-
error_info2 = error_utils.ErrorInfo.from_json(json_dict)
|
51
|
-
self.assertIsNot(error_info2, error_info)
|
52
|
-
self.assertEqual(error_info2, error_info)
|
53
|
-
|
54
|
-
def test_format(self):
|
55
|
-
error_info = error_utils.ErrorInfo(
|
56
|
-
tag='ValueError.ZeroDivisionError',
|
57
|
-
description='Bad call to `foo`',
|
58
|
-
stacktrace='Traceback (most recent call last)',
|
59
|
-
)
|
60
|
-
self.assertEqual(
|
61
|
-
error_info.format(compact=False),
|
62
|
-
inspect.cleandoc(
|
63
|
-
"""
|
64
|
-
ErrorInfo(
|
65
|
-
tag='ValueError.ZeroDivisionError',
|
66
|
-
description='Bad call to `foo`',
|
67
|
-
stacktrace='Traceback (most recent call last)'
|
68
|
-
)
|
69
|
-
"""
|
70
|
-
)
|
71
|
-
)
|
72
|
-
|
73
|
-
|
74
18
|
class CatchErrorsTest(unittest.TestCase):
|
75
19
|
|
76
20
|
def assert_caught_error(self, func, errors_to_catch):
|
@@ -48,13 +48,16 @@ class TextColorTest(unittest.TestCase):
|
|
48
48
|
block_color = text_color.colored(
|
49
49
|
'TEXT', color='white', background='blue'
|
50
50
|
).split('TEXT')[0]
|
51
|
-
|
52
|
-
colored_text,
|
51
|
+
expected = (
|
53
52
|
f'{origin_color}Hi {block_color}<< foo >>{reset}{origin_color}\n'
|
54
53
|
'<# print x if x is present #>\n<% if x %>\n'
|
55
54
|
f'{block_color}<< x >>{reset}{origin_color}\n'
|
56
55
|
f'<% endif %>{reset}'
|
57
56
|
)
|
57
|
+
self.assertTrue(
|
58
|
+
# On some termcolor versions, the color codes are not applied.
|
59
|
+
colored_text == expected or colored_text == original_text
|
60
|
+
)
|
58
61
|
self.assertEqual(text_color.decolor(colored_text), original_text)
|
59
62
|
|
60
63
|
def test_colored_block_without_full_match(self):
|
@@ -65,7 +65,7 @@ pyglove/core/patching/pattern_based.py,sha256=UtSNB-ARNqVjXwZovjVi84QEoXUGLLBTgL
|
|
65
65
|
pyglove/core/patching/pattern_based_test.py,sha256=PW1EcVfsFPB6wtgwg3s4dzvigWn3b5S8eMNGo0SJiZ0,2771
|
66
66
|
pyglove/core/patching/rule_based.py,sha256=JAQp8mWeIOxwIdqusA3GmXia-fxQhQsxbUTmE329wF8,17038
|
67
67
|
pyglove/core/patching/rule_based_test.py,sha256=qfy0ILmczV_LMHWEnwo2y079OrJsGYO0nKxSZdmIUcI,18782
|
68
|
-
pyglove/core/symbolic/__init__.py,sha256=
|
68
|
+
pyglove/core/symbolic/__init__.py,sha256=VMQj8oW2hGaJwqgchBJbu5qXoJKaNizxv__vsYL4b7U,6057
|
69
69
|
pyglove/core/symbolic/base.py,sha256=3vOHKtanrksBv5B_0HAq2R_CnE355aPx1B9lyJNb5us,77683
|
70
70
|
pyglove/core/symbolic/base_test.py,sha256=yASIHIuWiUB1jf4nN-Y4XOjyvr8eQfRpr7s_1LZsu78,7188
|
71
71
|
pyglove/core/symbolic/boilerplate.py,sha256=sQ3G25r5bo_UmIdjreL4jkAuQCXIHVlvUfGjjkNod6Y,5955
|
@@ -80,6 +80,8 @@ pyglove/core/symbolic/dict.py,sha256=7IxKSjUsGulUcNk3xqQnJ2ubGNUbqcc0ZFe8cKiigKA
|
|
80
80
|
pyglove/core/symbolic/dict_test.py,sha256=3MATsFw9Ci0jVPbAT2ivKVZ3PCnBBBvbkMWKgpgl-Fk,72915
|
81
81
|
pyglove/core/symbolic/diff.py,sha256=zHfED0Bbq8G_HWNPj3vrOCWzt_062rFhx3BMlpCb9oo,16282
|
82
82
|
pyglove/core/symbolic/diff_test.py,sha256=EDiGHqqKhi-NeMxr-bgjBEqlquee_4l_0IM6hgAb9Mg,29400
|
83
|
+
pyglove/core/symbolic/error_info.py,sha256=rqRwfmnEibMixaS2G-P0VhKjkZl79qjO6EUItnATHlQ,3675
|
84
|
+
pyglove/core/symbolic/error_info_test.py,sha256=y9HdGbvhQ6O4KB7Yv-N5N18k6v6nhiV_f-r1lTImHMo,3041
|
83
85
|
pyglove/core/symbolic/flags.py,sha256=a_8VZEhJjkt-zk1v3jCjlfNe7vEG2FqFfAC4l-gKrzg,12090
|
84
86
|
pyglove/core/symbolic/flags_test.py,sha256=JDJcm6dYTlnktFsdNFjQszmHXf9bZnhrXMxi_jUiKUA,5483
|
85
87
|
pyglove/core/symbolic/functor.py,sha256=6g1eBZSfSB6lp5NSXtAMw--xRhAfkYipSJh2LCVPNTM,26723
|
@@ -88,8 +90,8 @@ pyglove/core/symbolic/inferred.py,sha256=E4zgphg6NNZad9Fl3jdHQOMZeqEp9XHq5OUYqXE
|
|
88
90
|
pyglove/core/symbolic/inferred_test.py,sha256=G6uPykONcChvs6vZujXHSWaYfjewLTVBscMqzzKNty0,1270
|
89
91
|
pyglove/core/symbolic/list.py,sha256=z8goU0ntd-Q5ADaCGiKsJwPhdRdQb0Kd_p-ZekXaLy4,30303
|
90
92
|
pyglove/core/symbolic/list_test.py,sha256=IAyFQ48nyczKUcPNZFKHBkX5oh7Xuxbnv3rRkONhbHw,61146
|
91
|
-
pyglove/core/symbolic/object.py,sha256=
|
92
|
-
pyglove/core/symbolic/object_test.py,sha256=
|
93
|
+
pyglove/core/symbolic/object.py,sha256=OZ6eK8qyaLsUKxFiV2GWL5Ol6FDzMrrkpWSRKRwIKAA,42726
|
94
|
+
pyglove/core/symbolic/object_test.py,sha256=rDP7lcQZTFdQCqeaNYs7ZfwvGanzHz7CHM33NCmRIFk,94391
|
93
95
|
pyglove/core/symbolic/origin.py,sha256=OSWMKjvPcISOXrzuX3lCQC8m_qaGl-9INsIB81erUnU,6124
|
94
96
|
pyglove/core/symbolic/origin_test.py,sha256=dU_ZGrGDetM_lYVMn3wQO0d367_t_t8eESe3NrKPBNE,3159
|
95
97
|
pyglove/core/symbolic/pure_symbolic.py,sha256=pvo15gn35_KLiGW_XrTjlx5ddmHbwpLr93VgbQ59uQ8,3231
|
@@ -139,8 +141,8 @@ pyglove/core/utils/contextual.py,sha256=RxBQkDM2gB6QwZj_2oMels6oh-zQPGJJlinZbbqH
|
|
139
141
|
pyglove/core/utils/contextual_test.py,sha256=OOcthquVyAekTqt1RyYcEMHaockMIokpbv4pSf13Nzs,3252
|
140
142
|
pyglove/core/utils/docstr_utils.py,sha256=5BY40kXozPKVGOB0eN8jy1P5_GHIzqFJ9FXAu_kzxaw,5119
|
141
143
|
pyglove/core/utils/docstr_utils_test.py,sha256=i33VT6zHXEuIIJ4PPg1bVSfaYSnUsC8yST_NfpT-Uds,4228
|
142
|
-
pyglove/core/utils/error_utils.py,sha256=
|
143
|
-
pyglove/core/utils/error_utils_test.py,sha256=
|
144
|
+
pyglove/core/utils/error_utils.py,sha256=U9Ms3G1a_WUXaFgWccyPL7yOIf4k8Wi0nyXJ3yIaIfY,5264
|
145
|
+
pyglove/core/utils/error_utils_test.py,sha256=gnsEwFmgDNNVNvuQyhSWai8GDfLoCuX_DMqYow9Q2l4,2547
|
144
146
|
pyglove/core/utils/formatting.py,sha256=Wn4d933LQLhuMIfjdRJgpxOThCxBxQrkRBa6Z1-hL_I,15591
|
145
147
|
pyglove/core/utils/formatting_test.py,sha256=hhg-nL6DyE5A2QA92ALHK5QtfAYKfPpTbBARF-IT1j0,14241
|
146
148
|
pyglove/core/utils/hierarchical.py,sha256=jwB-0FhqOspAymAkvJphRhPTQEsoShmKupCZpU3Vip4,19690
|
@@ -150,11 +152,11 @@ pyglove/core/utils/json_conversion_test.py,sha256=zA_cy7ixVL3sTf6i9BCXMlSH56Aa3J
|
|
150
152
|
pyglove/core/utils/missing.py,sha256=9gslt1lXd1qSEIuAFxUWu30oD-YdYcnm13eau1S9uqY,1445
|
151
153
|
pyglove/core/utils/missing_test.py,sha256=D6-FuVEwCyJemUiPLcwLmwyptqI5Bx0Pfipc2juhKSE,1335
|
152
154
|
pyglove/core/utils/text_color.py,sha256=xcCTCxY2qFNZs_jismMGus8scEXKBpYGAhpAgnz-MHk,4112
|
153
|
-
pyglove/core/utils/text_color_test.py,sha256=
|
155
|
+
pyglove/core/utils/text_color_test.py,sha256=cZ2JQyTFtEhEeSQhuS1_hWHTD4Din2i4ypoDRT1dvIg,2938
|
154
156
|
pyglove/core/utils/thread_local.py,sha256=i-CnyY3VREtLfAj4_JndBnsKuQLIgwG29ma8dAyRxbI,4839
|
155
157
|
pyglove/core/utils/thread_local_test.py,sha256=AOqsdNsA-cYMvJckqxb25ql3Y5kDW0qLfBW1cl85Bnw,6757
|
156
158
|
pyglove/core/utils/timing.py,sha256=gnHCA2IJ9DZ3Y0vb8ItB1Ap8ss8j_zN0OMUAdhoGy2Y,7550
|
157
|
-
pyglove/core/utils/timing_test.py,sha256=
|
159
|
+
pyglove/core/utils/timing_test.py,sha256=g5r55V938sSUWdmiJbssNbaJzRm_09wyfkKgJJYRwc4,5089
|
158
160
|
pyglove/core/utils/value_location.py,sha256=wAryIwQeEfrRddyGRk-KbLA7dnNDLhL-dSyFI9wIG5U,26756
|
159
161
|
pyglove/core/utils/value_location_test.py,sha256=X6Gih3IoYugziwXWH8VGz5bPeb3Kq0CfZxwbNVIsZJo,21338
|
160
162
|
pyglove/core/views/__init__.py,sha256=gll9ZBRYz4p_-LWOdzSR2a6UTWcJ8nR430trrP0yLCU,967
|
@@ -214,8 +216,8 @@ pyglove/ext/scalars/randoms.py,sha256=LkMIIx7lOq_lvJvVS3BrgWGuWl7Pi91-lA-O8x_gZs
|
|
214
216
|
pyglove/ext/scalars/randoms_test.py,sha256=nEhiqarg8l_5EOucp59CYrpO2uKxS1pe0hmBdZUzRNM,2000
|
215
217
|
pyglove/ext/scalars/step_wise.py,sha256=IDw3tuTpv0KVh7AN44W43zqm1-E0HWPUlytWOQC9w3Y,3789
|
216
218
|
pyglove/ext/scalars/step_wise_test.py,sha256=TL1vJ19xVx2t5HKuyIzGoogF7N3Rm8YhLE6JF7i0iy8,2540
|
217
|
-
pyglove-0.4.5.
|
218
|
-
pyglove-0.4.5.
|
219
|
-
pyglove-0.4.5.
|
220
|
-
pyglove-0.4.5.
|
221
|
-
pyglove-0.4.5.
|
219
|
+
pyglove-0.4.5.dev202505160810.dist-info/licenses/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
|
220
|
+
pyglove-0.4.5.dev202505160810.dist-info/METADATA,sha256=VWfNPs2xHEwUAa7wIVLCBwCGp7bb7wPV5Sap6ewTZ00,7089
|
221
|
+
pyglove-0.4.5.dev202505160810.dist-info/WHEEL,sha256=Nw36Djuh_5VDukK0H78QzOX-_FQEo6V37m3nkm96gtU,91
|
222
|
+
pyglove-0.4.5.dev202505160810.dist-info/top_level.txt,sha256=wITzJSKcj8GZUkbq-MvUQnFadkiuAv_qv5qQMw0fIow,8
|
223
|
+
pyglove-0.4.5.dev202505160810.dist-info/RECORD,,
|
File without changes
|
{pyglove-0.4.5.dev202505150810.dist-info → pyglove-0.4.5.dev202505160810.dist-info}/licenses/LICENSE
RENAMED
File without changes
|
{pyglove-0.4.5.dev202505150810.dist-info → pyglove-0.4.5.dev202505160810.dist-info}/top_level.txt
RENAMED
File without changes
|