代码之家  ›  专栏  ›  技术社区  ›  Steven Sproat

TypeError:在重新打包后的单元测试期间,未绑定方法\uuuu init \uuuuuu()

  •  1
  • Steven Sproat  · 技术社区  · 14 年前

    我刚刚重新打包了我的程序。以前,所有模块都在“whyteboard”包下,其中“fakewidgets”包包含一堆虚拟GUI测试对象。

    现在,我所有的模块都在包中,例如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类时使用了一些技巧,即使它们是mock。 __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())
    
    4 回复  |  直到 14 年前
        1
  •  3
  •   aaronasterling    14 年前

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

    在你发布的旧文件里, 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来说,你不应该看到 wx . 如果我错了,那你就什么都看不见了,因为你会把它换掉 ScrolledWindowDummy 一个没有类型的类 DummyMeta

        2
  •  1
  •   nate c    14 年前

    代码是相同的,只是我的测试导入的代码不同于从新包中拉入的代码

    查看更改sys.path时会发生什么。

        3
  •  1
  •   bukzor    14 年前

    wx wx.ScrolledWindow 在定义 class Canvas Canvas.__init__ . 我强烈怀疑这些会有所不同。

    你在耍什么花招吗 __new__ 或者元类之类的?

        4
  •  1
  •   Ivo van der Wijk    14 年前

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

    import fakewidgets
    import wx
    

    口述

    import wx
    
    wx.Window = Window
    # for all other relevant widgets