Files
nuitka-mirror/tests/basics/FunctionsTest.py
Kay Hayen 0ac329ec01 Scons: Changed error message for using MinGW64 on newer Python to also mention Zig
* Also enhanced reporting error exit reporting through the scons logger to provide
  the exception in the compilation report.

* More error exits in scons should do this.
2026-01-28 13:44:29 +01:00

610 lines
12 KiB
Python

# Copyright 2025, Kay Hayen, mailto:kay.hayen@gmail.com find license text at end of file
"""Various kinds of functions with small specialties."""
from __future__ import print_function
import inspect
import sys
# pylint: disable=redefined-outer-name
var_on_module_level = 1
def closureTest1(some_arg): # pylint: disable=unused-argument
x = 3
def enclosed(_f="default_value"):
return x
return enclosed
print("Call closured function returning function:", closureTest1(some_arg="ignored")())
def closureTest2(some_arg): # pylint: disable=unused-argument
def enclosed(_f="default_value"):
return x
x = 4
return enclosed
print("Call closured function returning function:", closureTest2(some_arg="ignored")())
def defaultValueTest1(_no_default, some_default_constant=1):
return some_default_constant
print(
"Call function with 2 parameters, one defaulted, and check that the default value is used:",
defaultValueTest1("ignored"),
)
def defaultValueTest1a(
_no_default, some_default_constant_1=1, some_default_constant_2=2
):
return some_default_constant_2 - some_default_constant_1
print(
"Call function with 3 parameters, 2 defaulted, check they are used correctly:",
defaultValueTest1a("ignored"),
)
def defaultValueTest2(_no_default, some_default_variable=var_on_module_level * 2):
return some_default_variable
print(
"Call function with 2 parameters, 1 defaulted with an expression, check its result",
defaultValueTest2("ignored"),
)
var_on_module_level = 2
print(
"Call function with 2 parameters, 1 defaulted with an expression, values have changed since, check its result",
defaultValueTest2("ignored"),
)
def contractionTest():
j = 2
return [j + i for i in range(8)]
print("Call function that returns a list contraction:", contractionTest())
def defaultValueTest3a(
_no_default, funced_defaulted=defaultValueTest2(var_on_module_level)
):
return [i + funced_defaulted for i in range(8)]
print(
"Call function that has a default value coming from a function call:",
defaultValueTest3a("ignored"),
)
def defaultValueTest3b(
_no_default, funced_defaulted=defaultValueTest2(var_on_module_level)
):
local_var = [funced_defaulted + i for i in range(8)]
return local_var
print(
"Call function that returns a list contraction result via a local variable:",
defaultValueTest3b("ignored"),
)
def defaultValueTest3c(
_no_default, funced_defaulted=defaultValueTest2(var_on_module_level)
):
local_var = [[j + funced_defaulted + 1 for j in range(i)] for i in range(8)]
return local_var
print(
"Call function that returns a nested list contraction with input from default parameter",
defaultValueTest3c("ignored"),
)
def defaultValueTest4(_no_default, funced_defaulted=lambda x: x**2):
return funced_defaulted(4)
print(
"Call function that returns value calculated by a lambda function as default parameter",
defaultValueTest4("ignored"),
)
def defaultValueTest4a(_no_default, funced_defaulted=lambda x: x**2):
c = 1
d = funced_defaulted(1)
r = (i + j + c + d for i, j in zip(range(8), range(9)))
l = []
for x in r:
l.append(x)
return l
print(
"Call function that has a lambda calculated default parameter and a generator expression",
defaultValueTest4a("ignored"),
)
def defaultValueTest4b(_no_default, funced_defaulted=lambda x: x**3):
d = funced_defaulted(1)
# Nested generators
l = []
for x in ((d + j for j in range(4)) for i in range(8)):
for y in x:
l.append(y)
return l
print(
"Call function that has a lambda calculated default parameter and a nested generator expression",
defaultValueTest4b("ignored"),
)
def defaultValueTest5(_no_default, tuple_defaulted=(1, 2, 3)):
return tuple_defaulted
print("Call function with default value that is a tuple", defaultValueTest5("ignored"))
def defaultValueTest6(
_no_default, list_defaulted=[1, 2, 3]
): # pylint: disable=dangerous-default-value
return list_defaulted
print("Call function with default value that is a list", defaultValueTest6("ignored"))
x = len("hey")
# TODO: Doesn't belong here.
def in_test(a):
# if 7 in a:
# print "hey"
# pylint: disable=pointless-statement
8 in a # @NoEffect
9 not in a # @NoEffect
in_test([8])
try:
in_test(9)
except TypeError:
pass
def my_deco(function):
def new_function(c, d):
return function(d, c)
return new_function
@my_deco
def decoriert(a, b): # pylint: disable=unused-argument
def subby(a):
return 2 + a
return 1 + subby(b)
print("Function with decoration", decoriert(3, 9))
def functionWithGlobalReturnValue():
global a # pylint: disable=global-statement
return a
a = "oh common"
some_constant_tuple = (2, 5, 7)
some_semiconstant_tuple = (2, 5, a)
f = a * 2
print(defaultValueTest1("ignored"))
# The change of the default variable doesn't influence the default
# parameter of defaultValueTest2, that means it's also calculated
# at the time the function is defined.
module_level = 7
print(defaultValueTest2("also ignored"))
def starArgTest(a, b, c):
return a, b, c
print("Function called with star arg from tuple:")
star_list_arg = (11, 44, 77)
print(starArgTest(*star_list_arg))
print("Function called with star arg from list:")
star_list_arg = [7, 8, 9]
print(starArgTest(*star_list_arg))
star_dict_arg = {"a": 9, "b": 3, "c": 8}
print("Function called with star arg from dict")
print(starArgTest(**star_dict_arg))
lambda_func = lambda a, b: a < b
lambda_args = (8, 9)
print("Lambda function called with star args from tuple:")
print(lambda_func(*lambda_args))
print("Lambda function called with star args from list:")
lambda_args = [8, 7]
print(lambda_func(*lambda_args))
print("Generator function without context:")
def generator_without_context_function():
gen = (x for x in range(9))
return tuple(gen)
print(generator_without_context_function())
print("Generator function with 2 iterateds:")
def generator_with_2_fors():
return tuple((x, y) for x in range(2) for y in range(3))
print(generator_with_2_fors())
def someYielder():
yield 1
yield 2
def someYieldFunctionUser():
print("someYielder", someYielder())
result = []
for a in someYielder():
result.append(a)
return result
print("Function that uses some yielding function coroutine:")
print(someYieldFunctionUser())
def someLoopYielder():
for i in (0, 1, 2):
yield i
def someLoopYieldFunctionUser():
result = []
for a in someLoopYielder():
result.append(a)
return result
print("Function that uses some yielding function coroutine that loops:")
print(someLoopYieldFunctionUser())
def someGeneratorClosureUser():
def someGenerator():
def userOfGeneratorLocalVar():
return x + 1
x = 2
yield userOfGeneratorLocalVar()
yield 6
gen = someGenerator()
return [next(gen), next(gen)]
print(
"Function generator that uses a local function accessing its local variables to yield:"
)
print(someGeneratorClosureUser())
def someClosureUsingGeneratorUser():
offered = 7
def someGenerator():
yield offered
return next(someGenerator())
print("Function generator that yield from its closure:")
print(someClosureUsingGeneratorUser())
print("Function call with both star args and named args:")
def someFunction(a, b, c, d):
print(a, b, c, d)
someFunction(a=1, b=2, **{"c": 3, "d": 4})
print("Order of evaluation of function and args:")
def getFunction():
print("getFunction", end="")
def x(y, u, a, k):
return y, u, k, a
return x
def getPlainArg1():
print("getPlainArg1", end="")
return 9
def getPlainArg2():
print("getPlainArg2", end="")
return 13
def getKeywordArg1():
print("getKeywordArg1", end="")
return "a"
def getKeywordArg2():
print("getKeywordArg2", end="")
return "b"
getFunction()(getPlainArg1(), getPlainArg2(), k=getKeywordArg1(), a=getKeywordArg2())
print()
def getListStarArg():
print("getListStarArg", end="")
return [1]
def getDictStarArg():
print("getDictStarArg", end="")
return {"k": 9}
print("Same with star args:")
getFunction()(getPlainArg1(), a=getKeywordArg1(), *getListStarArg(), **getDictStarArg())
print()
print("Dictionary creation order:")
d = {getKeywordArg1(): getPlainArg1(), getKeywordArg2(): getPlainArg2()}
print()
print("Throwing an exception to a generator function:")
def someGeneratorFunction():
try:
yield 1
yield 2
except Exception: # pylint: disable=broad-except
yield 3
yield 4
gen1 = someGeneratorFunction()
print("Fresh Generator Function throwing gives", end="")
try:
print(gen1.throw(ValueError)),
except ValueError:
print("exception indeed")
gen2 = someGeneratorFunction()
print("Used Generator Function throwing gives", end="")
next(gen2)
print(gen2.throw(ValueError), "indeed")
gen3 = someGeneratorFunction()
print("Fresh Generator Function close gives", end="")
print(gen3.close())
gen4 = someGeneratorFunction()
print("Used Generator Function that mis-catches close gives", end="")
next(gen4)
try:
print(gen4.close(), end="")
except RuntimeError:
print("runtime exception indeed")
gen5 = someGeneratorFunction()
print("Used Generator Function close gives", end="")
next(gen5)
next(gen5)
next(gen5)
print(gen5.close(), end="")
def receivingGenerator():
while True:
a = yield 4
yield a
print("Generator function that receives", end="")
gen6 = receivingGenerator()
print(next(gen6), end="")
print(gen6.send(5), end="")
print(gen6.send(6), end="")
print(gen6.send(7), end="")
print(gen6.send(8))
print("Generator function whose generator is copied", end="")
def generatorFunction():
yield 1
yield 2
gen7 = generatorFunction()
next(gen7)
gen8 = iter(gen7)
print(next(gen8))
def doubleStarArgs(*a, **d):
return a, d
try:
from UserDict import UserDict
except ImportError:
print("Using Python3, making own non-dict dict:")
class UserDict(dict):
pass
print("Function that has keyword argument matching the list star arg name", end="")
print(doubleStarArgs(1, **UserDict(a=2)))
def generatorFunctionUnusedArg(_a):
yield 1
generatorFunctionUnusedArg(3)
def closureHavingGenerator(arg):
def gen(_x=1):
yield arg
return gen()
print("Function generator that has a closure and default argument", end="")
print(list(closureHavingGenerator(3)))
def functionWithDualStarArgsAndKeywordsOnly(a1, a2, a3, a4, b):
return a1, a2, a3, a4, b
l = [1, 2, 3]
d = {"b": 8}
print(
"Dual star args, but not positional call",
functionWithDualStarArgsAndKeywordsOnly(a4=1, *l, **d),
)
def posDoubleStarArgsFunction(a, b, c, *l, **d):
return a, b, c, l, d
l = [2]
d = {"other": 7, "c": 3}
print("Dual star args consuming function", posDoubleStarArgsFunction(1, *l, **d))
for value in sorted(dir()):
main_value = getattr(sys.modules["__main__"], value)
if inspect.isfunction(main_value):
print(
main_value,
main_value.__code__.co_varnames[: main_value.__code__.co_argcount],
inspect.getargs(main_value.__code__),
) #
# TODO: Make this work as well, currently disabled, because of nested arguments not
# being compatible yet.
# print inspect.getargspec( main_value )
# Python tests originally created or extracted from other peoples work. The
# parts were too small to be protected.
#
# 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.