1# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com 2# 3# Python tests originally created or extracted from other peoples work. The 4# parts were too small to be protected. 5# 6# Licensed under the Apache License, Version 2.0 (the "License"); 7# you may not use this file except in compliance with the License. 8# You may obtain a copy of the License at 9# 10# http://www.apache.org/licenses/LICENSE-2.0 11# 12# Unless required by applicable law or agreed to in writing, software 13# distributed under the License is distributed on an "AS IS" BASIS, 14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15# See the License for the specific language governing permissions and 16# limitations under the License. 17# 18try: 19 from collections.abc import OrderedDict 20except ImportError: 21 from collections import OrderedDict 22 23print("Call order of Python3 metaclasses:") 24 25 26def a(): 27 x = 1 28 29 class A: 30 print("Class body a.A is evaluating closure x", x) 31 32 print("Called", a) 33 34 return A 35 36 37def b(): 38 class B: 39 pass 40 41 print("Called", b) 42 43 return B 44 45 46def displayable(dictionary): 47 return sorted(dictionary.items()) 48 49 50def m(): 51 class M(type): 52 def __new__(cls, class_name, bases, attrs, **over): 53 print( 54 "Metaclass M.__new__ cls", 55 cls, 56 "name", 57 class_name, 58 "bases", 59 bases, 60 "dict", 61 displayable(attrs), 62 "extra class defs", 63 displayable(over), 64 ) 65 66 return type.__new__(cls, class_name, bases, attrs) 67 68 def __init__(self, name, bases, attrs, **over): 69 print( 70 "Metaclass M.__init__", 71 name, 72 bases, 73 displayable(attrs), 74 displayable(over), 75 ) 76 super().__init__(name, bases, attrs) 77 78 def __prepare__(metacls, bases, **over): # @NoSelf 79 print("Metaclass M.__prepare__", metacls, bases, displayable(over)) 80 return OrderedDict() 81 82 print("Called", m) 83 84 return M 85 86 87def d(): 88 print("Called", d) 89 90 return 1 91 92 93def e(): 94 print("Called", e) 95 96 return 2 97 98 99class C1(a(), b(), other=d(), metaclass=m(), yet_other=e()): 100 import sys 101 102 # TODO: Enable this. 103 # print("C1 locals type is", type(sys._getframe().f_locals)) 104 105 106print("OK, class created", C1) 107 108print("Attribute C1.__dict__ has type", type(C1.__dict__)) 109 110 111print("Function local classes can be made global and get proper __qualname__:") 112 113 114def someFunctionWithLocalClassesMadeGlobal(): 115 # Affects __qualname__ only in Python3.4 or higher, not in Python3.2 116 global C 117 118 class C: 119 pass 120 121 class D: 122 pass 123 124 try: 125 print("Nested class qualname is", D.__qualname__) 126 except AttributeError: 127 # Python3.2 128 pass 129 130 try: 131 print("Local class made global qualname is", C.__qualname__) 132 except AttributeError: 133 pass 134 135 136someFunctionWithLocalClassesMadeGlobal() 137 138print("Function in a class with private name") 139 140 141class someClassWithPrivateArgumentNames: 142 def f(self, *, __kw: 1): 143 pass 144 145 146print(someClassWithPrivateArgumentNames.f.__annotations__) 147print("OK.") 148