我刚刚重新包装了我的程序。以前所有模块都在“whyteboard”包下,带有一个包含一堆虚拟GUI测试对象的“fakewidgets”包。
现在,我的所有模块都在包中,例如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 :(得分:3)
当你import whyteboard.test
时,会自动运行whyteboard.test.fakewidgets.core
吗?我认为问题是在模拟代码运行之前正在创建{em} {em}。这解释了转换。
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
类,并将为您提供发生此情况的文件和行号。实质上,对于MRO,你不应该看到Canvas
的任何内容。如果我错了,那么你根本就不会看到任何东西,因为在创建任何名为“Canvas”的类之前,你将用一个没有类型wx
的类替换ScrolledWindowDummy
。
答案 1 :(得分:1)
代码是一样的,只是我的测试导入的代码与新软件包的输入不同
这听起来好像你的进口正在进口你没想到的东西。一旦我将一个文件命名为与系统模块相同的文件。我花了几个小时才弄清楚出了什么问题。
查看更改sys.path时会发生什么。
答案 2 :(得分:1)
请在wx
的定义之前打印wx.ScrolledWindow
和class Canvas
,并将其作为Canvas.__init__
的第一行。我强烈怀疑这些会有所不同。
您是否正在使用__new__
或元类等进行任何欺骗?
答案 3 :(得分:1)
确保fakewidgets是第一个导入wx模块,这意味着导入顺序很重要,例如。
import fakewidgets
import wx
或者,代替 dict .update技巧,明确替换名称,即
import wx
wx.Window = Window
# for all other relevant widgets
同样,仍然要确保fakewidgets是第一个访问wx模块的人。