direct: Clean up broken usage of "types" module with Python 3

This commit is contained in:
Daniel 2022-12-15 20:29:07 +01:00 committed by rdb
parent fdcfaf69b0
commit 24c14296c0
3 changed files with 54 additions and 20 deletions

View File

@ -11,12 +11,15 @@ import weakref
import random import random
import builtins import builtins
deadEndTypes = (bool, types.BuiltinFunctionType, deadEndTypes = frozenset((
types.BuiltinMethodType, complex, types.BuiltinFunctionType, types.BuiltinMethodType,
float, int, types.CodeType, types.FunctionType,
type(None), type(NotImplemented), types.GeneratorType, types.CoroutineType,
type, types.CodeType, types.FunctionType, types.AsyncGeneratorType,
bytes, str, tuple) bool, complex, float, int, type,
bytes, str, list, tuple,
type(None), type(NotImplemented)
))
def _createContainerLeak(): def _createContainerLeak():
@ -547,6 +550,23 @@ class FindContainers(Job):
# if we hit a dead end, start over from another container # if we hit a dead end, start over from another container
curObjRef = None curObjRef = None
# types.CellType was added in Python 3.8
if sys.version_info >= (3, 8) and type(curObj) is types.CellType:
child = curObj.cell_contents
hasLength = self._hasLength(child)
notDeadEnd = not self._isDeadEnd(child)
if hasLength or notDeadEnd:
objRef = ObjectRef(Indirection(evalStr='.cell_contents'),
id(child), parentObjRef)
yield None
if hasLength:
for i in self._addContainerGen(child, objRef):
yield None
if notDeadEnd:
self._addDiscoveredStartRef(child, objRef)
curObjRef = objRef
continue
if hasattr(curObj, '__dict__'): if hasattr(curObj, '__dict__'):
child = curObj.__dict__ child = curObj.__dict__
hasLength = self._hasLength(child) hasLength = self._hasLength(child)

View File

@ -3,7 +3,10 @@ from direct.showbase.PythonUtil import Queue, invertDictLossless
from direct.showbase.PythonUtil import safeRepr from direct.showbase.PythonUtil import safeRepr
from direct.showbase.Job import Job from direct.showbase.Job import Job
from direct.showbase.JobManagerGlobal import jobMgr from direct.showbase.JobManagerGlobal import jobMgr
from direct.showbase.ContainerLeakDetector import deadEndTypes
import types import types
import sys
import io
class ContainerReport(Job): class ContainerReport(Job):
@ -89,14 +92,6 @@ class ContainerReport(Job):
if isinstance(parentObj, (str, bytes)): if isinstance(parentObj, (str, bytes)):
continue continue
if type(parentObj) in (types.ModuleType, types.InstanceType):
child = parentObj.__dict__
if self._examine(child):
assert self._queue.back() is child
self._instanceDictIds.add(id(child))
self._id2pathStr[id(child)] = str(self._id2pathStr[id(parentObj)])
continue
if isinstance(parentObj, dict): if isinstance(parentObj, dict):
key = None key = None
attr = None attr = None
@ -126,7 +121,25 @@ class ContainerReport(Job):
del attr del attr
continue continue
if type(parentObj) is not types.FileType: # types.CellType was added in Python 3.8
if sys.version_info >= (3, 8) and type(parentObj) is types.CellType:
child = parentObj.cell_contents
if self._examine(child):
assert (self._queue.back() is child)
self._instanceDictIds.add(id(child))
self._id2pathStr[id(child)] = str(self._id2pathStr[id(parentObj)]) + '.cell_contents'
continue
if hasattr(parentObj, '__dict__'):
# Instance of a class
child = parentObj.__dict__
if self._examine(child):
assert (self._queue.back() is child)
self._instanceDictIds.add(id(child))
self._id2pathStr[id(child)] = str(self._id2pathStr[id(parentObj)])
continue
if not isinstance(parentObj, io.TextIOWrapper):
try: try:
itr = iter(parentObj) itr = iter(parentObj)
except: except:
@ -161,7 +174,10 @@ class ContainerReport(Job):
childName = None childName = None
child = None child = None
for childName in childNames: for childName in childNames:
child = getattr(parentObj, childName) try:
child = getattr(parentObj, childName)
except:
continue
if id(child) not in self._visitedIds: if id(child) not in self._visitedIds:
self._visitedIds.add(id(child)) self._visitedIds.add(id(child))
if self._examine(child): if self._examine(child):
@ -198,9 +214,7 @@ class ContainerReport(Job):
self._type2id2len[type(obj)][objId] = length self._type2id2len[type(obj)][objId] = length
def _examine(self, obj): def _examine(self, obj):
# return False if it's an object that can't contain or lead to other objects # return False if it's an object that can't contain or lead to other objects
if type(obj) in (bool, types.BuiltinFunctionType, types.BuiltinMethodType, if type(obj) in deadEndTypes:
complex, float, int, type(None), type(NotImplemented),
type, types.CodeType, types.FunctionType):
return False return False
# if it's an internal object, ignore it # if it's an internal object, ignore it
if id(obj) in ContainerReport.PrivateIds: if id(obj) in ContainerReport.PrivateIds:
@ -243,7 +257,7 @@ class ContainerReport(Job):
for i in self._outputType(type, **kArgs): for i in self._outputType(type, **kArgs):
yield None yield None
otherTypes = list(set(self._type2id2len.keys()).difference(set(initialTypes))) otherTypes = list(set(self._type2id2len.keys()).difference(set(initialTypes)))
otherTypes.sort() otherTypes.sort(key=lambda obj: obj.__name__)
for type in otherTypes: for type in otherTypes:
for i in self._outputType(type, **kArgs): for i in self._outputType(type, **kArgs):
yield None yield None

0
direct/src/showbase/GarbageReport.py Executable file → Normal file
View File