2010-08-01 73 views
1

我刚刚重新打包了我的程序。以前,所有模块都处于“whyteboard”包中,包含一个包含一组虚拟GUI测试对象的“fakewidgets”包。TypeError:未绑定方法__init __()....在重新打包后的单元测试期间

现在,我所有的模块都在包装中,例如, 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 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()) 
+0

为什么你明确调用'wx.ScrolledWindow .__ init __(self,...)'而不是'super(Canvas,self).__ init __(...)'? – 2010-08-01 21:12:37

+0

无论如何我都会得到相同的错误。 – 2010-08-01 21:25:48

+0

“假”和真正的wx类之间明显存在混淆。你的诡计是如何工作的?你如何实例化你的Canvas类? – 2010-08-29 13:21:08

回答

3

当你import 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__'] 

在您发布的旧文件,fakewidgetscanvas之前进口。

如果不工作,任何其他进口前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

+0

感谢您的反馈,今天下班后我会进行调查。我想知道我的包裹的进口是否干扰了某种程度。 – 2010-08-31 10:24:49

+0

是的,在我的测试软件包的__init__中导入“fakewidgets”软件包后,似乎在破坏事情。从那里删除导入并将测试中的伪装导入移动到最终导入似乎已经修复了它。我怀疑在我使用的Mock框架中可能存在一个错误,似乎并没有很好地处理嵌套调用。 – 2010-08-31 21:05:51

+0

@Steven我想你有什么是倒退的。您希望伪造的小部件被导入_before_ canvas,以便画布仅访问模拟。如果它使bug消失,看起来框架中可能存在错误。你运行了我给你的元类吗?这应该会在五分钟内让你到达底部。 – aaronasterling 2010-08-31 21:22:24

1

The code is the same, just the code for my tests' imports are different to pull in from the new packages

这听起来好像你的进口是进口的东西你没有想到的。一旦我将我的文件命名为与系统模块相同的文件。我花了数小时才弄清楚出了什么问题。

看看当你改变sys.path时会发生什么。

+0

我的文件没有任何冲突 - (除了“test”可以从任何python导入,所以我尝试将它重命名为“测试”)。仍然没有区别。我也玩过sys.path,但无济于事 – 2010-08-03 12:31:39

1

请在class Canvas的定义和第一行Canvas.__init__的前面打印wxwx.ScrolledWindow。我强烈怀疑这些会有所不同。

你是否在做任何与__new__或元类的欺骗?

+0

我的确尝试这样做,但似乎“nosetests”不打印出任何不在测试用例中的输出。 – 2010-08-31 10:39:33

1

确保fakewidgets是第一个导入wx模块,这意味着导入顺序很重要,例如,

import fakewidgets 
import wx 

另外,在字典 .update招代替,明确更换名称,即

import wx 

wx.Window = Window 
# for all other relevant widgets 

此外,还确保fakewidgets是第一个访问WX模块。

相关问题