pyglove 0.4.5.dev202501080809__py3-none-any.whl → 0.4.5.dev202501081746__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.
@@ -0,0 +1,100 @@
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
+ """Python code permissions."""
15
+
16
+ import contextlib
17
+ import enum
18
+ from typing import Optional
19
+
20
+ from pyglove.core import utils
21
+
22
+
23
+ class CodePermission(enum.Flag):
24
+ """Permissions for code execution."""
25
+
26
+ # Allows assignment.
27
+ ASSIGN = enum.auto()
28
+
29
+ # Allows conditions.
30
+ CONDITION = enum.auto()
31
+
32
+ # Allows loops.
33
+ LOOP = enum.auto()
34
+
35
+ # Call functions or methods.
36
+ CALL = enum.auto()
37
+
38
+ # Allows exception.
39
+ EXCEPTION = enum.auto()
40
+
41
+ # Allows class definitions.
42
+ CLASS_DEFINITION = enum.auto()
43
+
44
+ # Allows function definitions.
45
+ FUNCTION_DEFINITION = enum.auto()
46
+
47
+ # Allows import.
48
+ IMPORT = enum.auto()
49
+
50
+ @classmethod
51
+ @property
52
+ def BASIC(cls) -> 'CodePermission': # pylint: disable=invalid-name
53
+ """Returns basic permissions."""
54
+ return CodePermission.ASSIGN | CodePermission.CALL
55
+
56
+ @classmethod
57
+ @property
58
+ def ALL(cls) -> 'CodePermission': # pylint: disable=invalid-name
59
+ """Returns all permissions."""
60
+ return (
61
+ CodePermission.BASIC | CodePermission.CONDITION | CodePermission.LOOP |
62
+ CodePermission.EXCEPTION | CodePermission.CLASS_DEFINITION |
63
+ CodePermission.FUNCTION_DEFINITION | CodePermission.IMPORT)
64
+
65
+
66
+ _TLS_CODE_RUN_PERMISSION = '__code_run_permission__'
67
+
68
+
69
+ @contextlib.contextmanager
70
+ def permission(perm: CodePermission):
71
+ """Context manager for controling the permission for code execution.
72
+
73
+ When the `permission` context manager is nested, the outtermost permission
74
+ will be used. This design allows users to control permission at the top level.
75
+
76
+ Args:
77
+ perm: Code execution permission.
78
+
79
+ Yields:
80
+ Actual permission applied.
81
+ """
82
+
83
+ outter_perm = utils.thread_local_get(_TLS_CODE_RUN_PERMISSION, None)
84
+
85
+ # Use the top-level permission as the actual permission
86
+ if outter_perm is not None:
87
+ perm = outter_perm
88
+
89
+ utils.thread_local_set(_TLS_CODE_RUN_PERMISSION, perm)
90
+
91
+ try:
92
+ yield perm
93
+ finally:
94
+ if outter_perm is None:
95
+ utils.thread_local_del(_TLS_CODE_RUN_PERMISSION)
96
+
97
+
98
+ def get_permission() -> Optional[CodePermission]:
99
+ """Gets the current permission for code execution."""
100
+ return utils.thread_local_get(_TLS_CODE_RUN_PERMISSION, None)
@@ -0,0 +1,93 @@
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
+ import unittest
15
+ from pyglove.core.coding import permissions
16
+
17
+
18
+ class CodePermissionTest(unittest.TestCase):
19
+
20
+ def assert_set(
21
+ self,
22
+ permission: permissions.CodePermission,
23
+ flag: permissions.CodePermission,
24
+ ):
25
+ self.assertEqual(permission & flag, flag)
26
+
27
+ def assert_not_set(
28
+ self,
29
+ permission: permissions.CodePermission,
30
+ flag: permissions.CodePermission,
31
+ ):
32
+ self.assertFalse(permission & flag)
33
+
34
+ def test_basic(self):
35
+ self.assert_set(
36
+ permissions.CodePermission.BASIC, permissions.CodePermission.ASSIGN
37
+ )
38
+ self.assert_set(
39
+ permissions.CodePermission.BASIC, permissions.CodePermission.CALL
40
+ )
41
+ self.assert_set(
42
+ permissions.CodePermission.BASIC, permissions.CodePermission.CALL
43
+ )
44
+
45
+ def test_all(self):
46
+ self.assert_set(
47
+ permissions.CodePermission.ALL, permissions.CodePermission.BASIC
48
+ )
49
+ self.assert_set(
50
+ permissions.CodePermission.ALL, permissions.CodePermission.CONDITION
51
+ )
52
+ self.assert_set(
53
+ permissions.CodePermission.ALL, permissions.CodePermission.LOOP
54
+ )
55
+ self.assert_set(
56
+ permissions.CodePermission.ALL, permissions.CodePermission.EXCEPTION
57
+ )
58
+ self.assert_set(
59
+ permissions.CodePermission.ALL,
60
+ permissions.CodePermission.CLASS_DEFINITION,
61
+ )
62
+ self.assert_set(
63
+ permissions.CodePermission.ALL,
64
+ permissions.CodePermission.FUNCTION_DEFINITION,
65
+ )
66
+ self.assert_set(
67
+ permissions.CodePermission.ALL, permissions.CodePermission.IMPORT
68
+ )
69
+
70
+ def test_xor(self):
71
+ self.assert_not_set(
72
+ permissions.CodePermission.ALL ^ permissions.CodePermission.BASIC,
73
+ permissions.CodePermission.BASIC,
74
+ )
75
+ self.assert_set(
76
+ permissions.CodePermission.ALL ^ permissions.CodePermission.BASIC,
77
+ permissions.CodePermission.CONDITION,
78
+ )
79
+
80
+ def test_permission_control(self):
81
+ self.assertIsNone(permissions.get_permission())
82
+ with permissions.permission(permissions.CodePermission.BASIC):
83
+ self.assertEqual(
84
+ permissions.get_permission(), permissions.CodePermission.BASIC
85
+ )
86
+ with permissions.permission(permissions.CodePermission.ALL):
87
+ self.assertEqual(
88
+ permissions.get_permission(), permissions.CodePermission.BASIC
89
+ )
90
+
91
+
92
+ if __name__ == '__main__':
93
+ unittest.main()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pyglove
3
- Version: 0.4.5.dev202501080809
3
+ Version: 0.4.5.dev202501081746
4
4
  Summary: PyGlove: A library for manipulating Python objects.
5
5
  Home-page: https://github.com/google/pyglove
6
6
  Author: PyGlove Authors
@@ -2,9 +2,17 @@ pyglove/__init__.py,sha256=YPUWALRDu4QuI7N3TUmVaVr513hUt0qXrjY582I1q5c,1352
2
2
  pyglove/core/__init__.py,sha256=eT7QvwXj-ers44ufDvIuy3J2PAckk5b4EVGbRiX_E-M,9284
3
3
  pyglove/core/logging.py,sha256=Sr5nLyUQmc4CAEYAq8qbP3ghpjmpz2sOuhq2A0tgQ6I,2456
4
4
  pyglove/core/logging_test.py,sha256=3z_c6wnxbqDbwUmSOAZzeDPXvzoweYL5QHUQVMJ5Xgo,1917
5
- pyglove/core/coding/__init__.py,sha256=nVKjJQYhvzJNr1zj0GuCsz_ltGLqhQEtBQj0zPiOkqA,998
5
+ pyglove/core/coding/__init__.py,sha256=Qn72755xebwK9_fYp7FAIkER49L1bLkxzEjYR6GFKrA,1470
6
+ pyglove/core/coding/errors.py,sha256=vstDb52lk5uJef2k_0_1dqvGv8eDYNq37IrqjGJ-cNc,3302
7
+ pyglove/core/coding/errors_test.py,sha256=fwOR8vLiRvLadubsccyE19hLHj-kThlCQt88qmUYk9M,2311
8
+ pyglove/core/coding/execution.py,sha256=fCJdONSwQhobtSrvjIySZ-t3qy6l1TdTM0qWFzIVWTM,10874
9
+ pyglove/core/coding/execution_test.py,sha256=MMYhkgjssGet_wQNUu-8moKZZkxNqfDxBiW3ahI0qrg,8417
6
10
  pyglove/core/coding/function_generation.py,sha256=2fCqcdcizVYtGYE6QGpw5m1kuH9Fp0OF4BjyJ4en6tw,1636
7
11
  pyglove/core/coding/function_generation_test.py,sha256=kbSwmZF8Vog0R0OTSpuzPblEbMLoRJ1TigeIrwDhHS8,2161
12
+ pyglove/core/coding/parsing.py,sha256=JXTdzFS9iB5-JVi9_-rDFORj_EZEtr7In8HBGHp09no,4084
13
+ pyglove/core/coding/parsing_test.py,sha256=XB-bd2Huj36GKmvmFjp3jRwr7NqhRd1Ag-AGNxr_ekk,3575
14
+ pyglove/core/coding/permissions.py,sha256=kd_gO1csXHpySsvazxmKBVe7dfLpX5GquRtu9q4ToRE,2729
15
+ pyglove/core/coding/permissions_test.py,sha256=GTEnCClTZWdFmqHk3U5P8mzOmIINtUeEkeJZApnaWVI,2935
8
16
  pyglove/core/detouring/__init__.py,sha256=ck_n2VSuU31HNVYQkbG4Zvnx90mNYtSVc2StN3rXbU8,1891
9
17
  pyglove/core/detouring/class_detour.py,sha256=ejuUr7UfRU3l9PrDxD0dpKmt2iqdDU6liHdebA1jEfQ,13312
10
18
  pyglove/core/detouring/class_detour_test.py,sha256=9aAK6qPiT0_HJe5oUpqMVTpoHv0wr_h6c4gWYKMTJoM,5507
@@ -199,8 +207,8 @@ pyglove/ext/scalars/randoms.py,sha256=LkMIIx7lOq_lvJvVS3BrgWGuWl7Pi91-lA-O8x_gZs
199
207
  pyglove/ext/scalars/randoms_test.py,sha256=nEhiqarg8l_5EOucp59CYrpO2uKxS1pe0hmBdZUzRNM,2000
200
208
  pyglove/ext/scalars/step_wise.py,sha256=IDw3tuTpv0KVh7AN44W43zqm1-E0HWPUlytWOQC9w3Y,3789
201
209
  pyglove/ext/scalars/step_wise_test.py,sha256=TL1vJ19xVx2t5HKuyIzGoogF7N3Rm8YhLE6JF7i0iy8,2540
202
- pyglove-0.4.5.dev202501080809.dist-info/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
203
- pyglove-0.4.5.dev202501080809.dist-info/METADATA,sha256=1rkODhRd0zayZYQ5lczr0q5i4XDQ2BQFAYnLRmS_39g,6860
204
- pyglove-0.4.5.dev202501080809.dist-info/WHEEL,sha256=A3WOREP4zgxI0fKrHUG8DC8013e3dK3n7a6HDbcEIwE,91
205
- pyglove-0.4.5.dev202501080809.dist-info/top_level.txt,sha256=wITzJSKcj8GZUkbq-MvUQnFadkiuAv_qv5qQMw0fIow,8
206
- pyglove-0.4.5.dev202501080809.dist-info/RECORD,,
210
+ pyglove-0.4.5.dev202501081746.dist-info/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
211
+ pyglove-0.4.5.dev202501081746.dist-info/METADATA,sha256=PEuAw0lfMfwC5GJNGA4epW90Em0jw24oyM3d8RdQVPs,6860
212
+ pyglove-0.4.5.dev202501081746.dist-info/WHEEL,sha256=A3WOREP4zgxI0fKrHUG8DC8013e3dK3n7a6HDbcEIwE,91
213
+ pyglove-0.4.5.dev202501081746.dist-info/top_level.txt,sha256=wITzJSKcj8GZUkbq-MvUQnFadkiuAv_qv5qQMw0fIow,8
214
+ pyglove-0.4.5.dev202501081746.dist-info/RECORD,,