Files
2026-07-13 12:40:42 +08:00

262 lines
4.8 KiB
Python

# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import inspect
import unittest
from test_case_base import TestCaseBase
import paddle
from paddle.jit.sot.utils import strict_mode_guard
def foo(x: int, y: paddle.Tensor):
z = 3
def local(a, b=5):
return a + x + z + b + y
return local(4) + z
def foo2(y: paddle.Tensor, x=1):
"""
Test strip default value
"""
z = 3
def local(a, b=5):
return a + x + z + b + y
return local(4)
def foo3(y: paddle.Tensor, x=1):
"""
Test Closure Band Default
"""
z = 3
def local(a, b=5):
nonlocal z
z = 4
return a + x + z + b + y
return local(4)
global_z = 3
def test_global(y: paddle.Tensor):
"""
Test Global variable
"""
def local(a, b=5):
global global_z
global_z += 1
return a + global_z + b + y
return local(1)
def multi(c):
return c + 2
def wrapper_function(func):
a = 2
def inner():
return func(a)
return inner
wrapped_multi = wrapper_function(multi)
def foo5(y: paddle.Tensor):
"""
Test incoming closures
"""
a = wrapped_multi()
return a
def outwrapper(func):
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
def foo6(y: paddle.Tensor):
"""
Test Decorator
"""
@outwrapper
def load_1(a, b=5):
return a + b
return load_1(1)
import numpy as np
def numpy_sum(m):
"""
Test loop call
Example: a->b->c->a
"""
a = np.array([1, 2, 3])
tmp = np.sum(a)
return m + 1
def lambda_closure(x, m):
"""
lambda closure.
"""
def break_graph_closure():
print("yes")
return x + m
return break_graph_closure()
# motivated by python builtin decorator
def kwargs_wrapper(func):
sig = inspect.signature(func)
def inner(*args, **kwargs):
return func(*args, **kwargs)
inner.__signature__ = sig
return inner
@kwargs_wrapper
def func7(a, b):
return a + b
def foo7():
return func7(3, 5)
def create_closure():
x = 1
def closure():
return x + 1
return closure
class TestClosure(TestCaseBase):
def test_closure(self):
self.assert_results(foo, 1, paddle.to_tensor(2))
self.assert_results(foo2, paddle.to_tensor(2))
self.assert_results(foo3, paddle.to_tensor(2))
self.assert_results_with_global_check(
test_global, ["global_z"], paddle.to_tensor(2)
)
self.assert_results(foo5, paddle.to_tensor(2))
self.assert_results(foo6, paddle.to_tensor(2))
self.assert_results(numpy_sum, paddle.to_tensor(1))
with strict_mode_guard(False):
self.assert_results(
lambda_closure, paddle.to_tensor(2), paddle.to_tensor(1)
)
class TestClosure2(TestCaseBase):
def test_closure(self):
self.assert_results(foo7)
# Side Effect.
def test_slice_in_for_loop(x, iter_num=3):
x = paddle.to_tensor(x)
a = []
# Use `paddle.full` so that static analysis can analyze the type of iter_num is Tensor
iter_num = paddle.full(
shape=[1], fill_value=iter_num, dtype="int32"
) # TODO(liym27): Delete it if the type of parameter iter_num can be resolved
for i in range(iter_num):
a.append(x)
for i in range(iter_num):
a[i] = x
out = a[2]
return out
class TestClosure3(TestCaseBase):
def test_closure(self):
tx = paddle.to_tensor([1.0, 2.0, 3.0])
# need side effect of list.
# self.assert_results(test_slice_in_for_loop, tx)
def non_local_test(t: paddle.Tensor):
a = 1
def func1():
nonlocal a
t = a
a = 2
return t
def func2():
nonlocal a
a = 1
return a
t += func1() # add 2
t += func2() # add 1
t += a # add 1
return t
class TestClosure4(TestCaseBase):
def test_closure(self):
tx = paddle.to_tensor([1.0])
self.assert_results(non_local_test, tx)
class TestCreateClosure(TestCaseBase):
def test_create_closure(self):
closure = create_closure()
self.assert_results(closure)
if __name__ == "__main__":
unittest.main()
# Instructions:
# LOAD_CLOSURE
# LOAD_DEREF
# LOAD_CLASSDEREF
# STORE_DEREF
# DELETE_DEREF
# STORE_GLOBAL