Skip to main content
 首页 » 编程设计

python之TypeError : unbound method __init__() . ...在重新打包后的单元测试期间

2025年05月04日18emanlee

我刚刚重新打包了我的程序。以前所有模块都位于“whyteboard”包下,“fakewidgets”包包含一堆虚拟 GUI 测试对象。<​​/p>

现在,我所有的模块都在包中,例如whyteboard.gui、whyteboard.misc、whyteboard.test - 这是 fakewidgets 现在所在的地方。

现在,在运行我的测试时,我得到一个异常,

  File "/home/steve/Documents/whyteboard/whyteboard/gui/canvas.py", line 77, in __init__ 
    wx.ScrolledWindow.__init__(self, tab, style=wx.NO_FULL_REPAINT_ON_RESIZE | wx.CLIP_CHILDREN) 
TypeError: unbound method __init__() must be called with ScrolledWindow instance as first argument (got Canvas instance instead) 

这是 有问题的类(class)

class Canvas(wx.ScrolledWindow): 
    def __init__(self, tab, gui, area): 
        wx.ScrolledWindow.__init__(self, tab, style=wx.NO_FULL_REPAINT_ON_RESIZE | wx.CLIP_CHILDREN) 

但是,除了单元测试之外,我的程序加载并运行正常。代码是一样的,只是我的测试导入的代码与从新包中提取的代码不同。

之前:

import os 
import wx 
 
import fakewidgets 
import gui 
import lib.mock as mock 
 
from canvas import Canvas, RIGHT, DIAGONAL, BOTTOM 
from fakewidgets.core import Bitmap, Event, Colour 
 
from lib.configobj import ConfigObj 
from lib.pubsub import pub 
from lib.validate import Validator 

现在:

import os 
import wx 
 
import whyteboard.test 
import whyteboard.gui.frame as gui 
 
from whyteboard.lib import ConfigObj, mock, pub, Validator 
from whyteboard.gui.canvas import Canvas, RIGHT, DIAGONAL, BOTTOM 
from whyteboard.test.fakewidgets.core import Bitmap, Event, Colour, PySimpleApp 

可能值得注意的是,fakewidgets 包做了一些欺骗,使我的程序认为它正在使用 wxPython 类,即使它们是模拟的。 这来自 whyteboard.test.fakewidgets 的 __init__

导入的模块
class Window(object): 
    def __init__(self, parent, *args, **kwds): 
        self.parent = parent 
        self.Enabled = True 
        self.calls = [] 
        self.size = (0, 0) 
        self.captured = False 
 
    def GetClientSizeTuple(self): 
        return (0, 0) 
        self.captured = True 
 
    def GetId(self): 
        pass 
 
    def Fit(self): 
        pass 
 
    def SetFocus(self): 
        pass 
 
    def PrepareDC(self, dc): 
        pass 
 
    def Destroy(self): 
        pass 
 
... 
 
 
class ScrolledWindow(Window): 
    def SetVirtualSize(self, *size): 
        pass 
 
    def SetVirtualSizeHints(self, *size): 
        pass 
 
import wx 
wx.__dict__.update(locals()) 

请您参考如下方法:

当您导入 whyteboard.test 时,它会自动运行 whyteboard.test.fakewidgets.core 吗?我认为问题是 Canvas 是在 模拟代码运行之前创建的。这解释了切换。

>>> import wx 
>>> class Test1(wx.Window): 
...    pass 
...  
>>> wx.Window = object 
>>> class Test2(wx.Window): 
...    pass 
...  
>>> dir(Test1)[:10] 
['AcceleratorTable', 'AcceptsFocus', 'AcceptsFocusFromKeyboard',  
 'AddChild', 'AddPendingEvent', 'AdjustForLayoutDirection',  
 'AssociateHandle', 'AutoLayout', 'BackgroundColour', 'BackgroundStyle'] 
>>> dir(Test2)[:10] 
['__class__', '__delattr__', '__dict__', '__doc__', '__format__',  
 '__getattribute__', '__hash__', '__init__', '__module__', '__new__'] 

在您发布的旧文件中,fakewidgets 是在 canvas 之前导入的。

如果这不起作用,请将此代码直接放在 import wx 之后,然后再进行任何其他导入:

import inspect 
 
class DummyMeta(type): 
    def __new__(meta, clsname, bases, clsdict): 
        if clsname == 'Canvas': 
            lineno = inspect.stack()[1][2] 
            print "creating Canvas with mro: {0}".format(inspect.getmro(bases[0])) 
            print "file:{0}:{1}".format(__file__, lineno) 
        return super(DummyMeta, meta).__new__(meta, clsname, bases, clsdict) 
 
class ScrolledWindowDummy(wx.Window): 
    __metaclass__ = DummyMeta 
 
wx.ScrolledWindow = ScrolledWindowDummy 

这将显示在模拟到位之前正在创建一个 Canvas 类,并将为您提供发生此情况的文件和行号。本质上,对于 MRO,您不应该从 wx 中看到任何内容。如果我错了,那么您根本看不到任何东西,因为您将在任何名为“Canvas”的类之前用一个没有类型 DummyMeta 的类替换了 ScrolledWindowDummy已创建。