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 builtins
deadEndTypes = (bool, types.BuiltinFunctionType,
types.BuiltinMethodType, complex,
float, int,
type(None), type(NotImplemented),
type, types.CodeType, types.FunctionType,
bytes, str, tuple)
deadEndTypes = frozenset((
types.BuiltinFunctionType, types.BuiltinMethodType,
types.CodeType, types.FunctionType,
types.GeneratorType, types.CoroutineType,
types.AsyncGeneratorType,
bool, complex, float, int, type,
bytes, str, list, tuple,
type(None), type(NotImplemented)
))
def _createContainerLeak():
@ -547,6 +550,23 @@ class FindContainers(Job):
# if we hit a dead end, start over from another container
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__'):
child = curObj.__dict__
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.Job import Job
from direct.showbase.JobManagerGlobal import jobMgr
from direct.showbase.ContainerLeakDetector import deadEndTypes
import types
import sys
import io
class ContainerReport(Job):
@ -89,14 +92,6 @@ class ContainerReport(Job):
if isinstance(parentObj, (str, bytes)):
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):
key = None
attr = None
@ -126,7 +121,25 @@ class ContainerReport(Job):
del attr
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:
itr = iter(parentObj)
except:
@ -161,7 +174,10 @@ class ContainerReport(Job):
childName = None
child = None
for childName in childNames:
child = getattr(parentObj, childName)
try:
child = getattr(parentObj, childName)
except:
continue
if id(child) not in self._visitedIds:
self._visitedIds.add(id(child))
if self._examine(child):
@ -198,9 +214,7 @@ class ContainerReport(Job):
self._type2id2len[type(obj)][objId] = length
def _examine(self, obj):
# 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,
complex, float, int, type(None), type(NotImplemented),
type, types.CodeType, types.FunctionType):
if type(obj) in deadEndTypes:
return False
# if it's an internal object, ignore it
if id(obj) in ContainerReport.PrivateIds:
@ -243,7 +257,7 @@ class ContainerReport(Job):
for i in self._outputType(type, **kArgs):
yield None
otherTypes = list(set(self._type2id2len.keys()).difference(set(initialTypes)))
otherTypes.sort()
otherTypes.sort(key=lambda obj: obj.__name__)
for type in otherTypes:
for i in self._outputType(type, **kArgs):
yield None

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