2010-08-01 76 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模塊。

相關問題