home *** CD-ROM | disk | FTP | other *** search
- # Source Generated with Decompyle++
- # File: in.pyo (Python 2.5)
-
- from gui.native.win.dockconstants import WM_EXITSIZEMOVE, WM_WINDOWPOSCHANGING, WM_SIZING, WM_NCHITTEST, WM_SYSCOMMAND, WM_USER, ABE_LEFT, ABE_RIGHT, ABM_REMOVE, SC_MAXIMIZE, SC_MINIMIZE, HTBOTTOMLEFT, HTLEFT, HTTOPLEFT, HTBOTTOMRIGHT, HTRIGHT, HTTOPRIGHT, SC_SIZE, ABM_SETPOS, WMSZ_LEFT, WMSZ_RIGHT, ABM_SETAUTOHIDEBAR, sideStrings, ABM_NEW, SWP_NOACTIVATE, SWP_NOMOVE, SWP_NOSIZE, ABM_GETSTATE, ABS_ALWAYSONTOP, HWND_BOTTOM, HWND_TOPMOST, ABE_TOP, ABE_BOTTOM, ABM_QUERYPOS, ABN_STATECHANGE, ABN_FULLSCREENAPP, ABN_POSCHANGED, ABN_WINDOWARRANGE, ABS_AUTOHIDE
- import ctypes
- import wx
- from wx import PyTimer
- from ctypes import c_uint, Structure, byref, c_int, POINTER, cast
- from logging import getLogger
- log = getLogger('dock')
- from gui.toolbox import Monitor
- from util import Delegate
- from util import default_timer
- from gui.native.win.winextensions import wxRectToRECT
- from ctypes.wintypes import DWORD, HANDLE, LPARAM, RECT
- user32 = ctypes.windll.user32
- SetWindowPos = user32.SetWindowPos
- MoveWindow = user32.MoveWindow
- shell32_SHAppBarMessage = ctypes.windll.shell32.SHAppBarMessage
- CallWindowProc = ctypes.windll.user32.CallWindowProcW
- DefWindowProc = ctypes.windll.user32.DefWindowProcW
-
- def SHAppBarMessage(msg, abd):
- return shell32_SHAppBarMessage(msg, byref(abd))
-
- ANIMATE_SECS = 0.1
- AUTOHIDE_TIMER_MS = 130
- ANIMATE_DELTA = 6
- UNKNOWN_MAX_FLAG = 61490
-
- sign = lambda v: if v > 0:
- passelif v < 0:
- pass0
-
- class Docker(object):
-
- def __init__(self, win, autohide = False, enabled = True):
- self.win = win
- self._side = None
- self.DockMargin = 30
-
- self.ShouldShowInTaskbar = lambda : True
- self.ShouldAlwaysStayOnTop = None
- self.RevealDurationMs = 300
- self.Animate = True
- self.autohidden = self.docking = self.docked = False
- self._enabled = enabled
- self._autohide = autohide
- self.bypassSizeEvents = False
- self.bypassMoveEvents = False
- self.reReserveTimer = None
- Bind = win.Bind
- BindWin32 = win.BindWin32
- Bind(wx.EVT_MOVING, self.OnMoving)
- Bind(wx.EVT_CLOSE, self.OnClose)
- Bind(wx.EVT_ACTIVATE, self.OnActivate)
- Bind(wx.EVT_DISPLAY_CHANGED, self.OnDisplayChanged)
- Bind(wx.EVT_SHOW, self.OnShow)
- BindWin32(WM_WINDOWPOSCHANGING, self.OnWindowPosChanging)
- BindWin32(WM_EXITSIZEMOVE, self.OnExitSizeMove)
- BindWin32(WM_SIZING, self.OnSizing)
- BindWin32(WM_NCHITTEST, self.OnNCHitTest)
- BindWin32(WM_SYSCOMMAND, self.OnSysCommand)
- self.appbar_cb_id = WM_USER + 100
- BindWin32(self.appbar_cb_id, self.AppBarCallback)
- self.firstShow = True
- self.wasDocked = False
- self.oldSize = None
- self.motiontrigger = False
- self.create_timer()
- self.OnDock = Delegate()
- self.OnHide = Delegate()
- self.LinkedWindows = []
-
-
- def __repr__(self):
- return '<Docker for %r>' % self.win
-
-
- def GetSide(self):
- if self._side == None:
- pos = self.win.Rect
- margin = self.DockMargin
- screenRect = monitor_rect(self.win)
- if pos.x < screenRect.X + margin and pos.Right > screenRect.X:
- self._side = ABE_LEFT
-
- if pos.Right > screenRect.Right - margin and pos.x < screenRect.Right:
- self._side = ABE_RIGHT
-
-
- return self._side
-
-
- def SetSide(self, side):
- self._side = side
-
- side = property(GetSide, SetSide)
-
- def OnDisplayChanged(self, event):
- log.debug('OnDisplayChanged')
- if self.docked and not (self.AutoHide):
- self.Undock(setFrameStyle = False)
- self.win.FitInScreen(Monitor.GetFromDeviceId(self.monId))
- self.Dock(setFrameStyle = False)
- self.bypassMoveEvents = True
- self.win.SetRect(self.dockedRect)
- self.bypassMoveEvents = False
- self.docking = True
- self.docked = False
- self.OnExitSizeMove()
- elif self.docked and self.AutoHide:
- onRight = self.side == ABE_RIGHT
- mon = Monitor.GetFromDeviceId(self.monId)
- monRect = mon.ClientArea
- xPos = None if onRight else monRect.Left - 1
- while onscreen(xPos, monRect.Y):
- mon = Monitor.GetFromPoint((xPos, monRect.Y))
- monRect = mon.ClientArea
- xPos = None if onRight else monRect.Left - 1
- if onRight:
- self.dockedRect = wx.Rect((monRect.Right - self.win.Size.width) + 1, monRect.Top, self.win.Size.width, monRect.Bottom - monRect.Top)
- else:
- self.dockedRect = wx.Rect(monRect.left - 1, monRect.Top, self.win.Size.width, monRect.Bottom - monRect.Top)
- self.bypassMoveEvents = True
- self.win.SetRect(self.dockedRect)
- self.bypassMoveEvents = False
- self.GoAway(monRect)
-
- event.Skip()
-
-
- def OnShow(self, event):
- if self.win.Shown:
- onRight = self.side == ABE_RIGHT
- mon = Monitor.GetFromWindow(self.win)
- monRect = mon.ClientArea
- atEdge = not None(onscreen if onRight else monRect.Left - 1, monRect.Y)
- if not self.wasDocked and self.firstShow and atEdge:
- pass
- shouldDock = not (self.AutoHide)
- if self.Enabled and shouldDock and self.side is not None and not (self.docked):
- self.Dock(setFrameStyle = self.firstShow)
- self.firstShow = False
- self.bypassMoveEvents = True
- self.win.SetRect(self.dockedRect)
- self.bypassMoveEvents = False
- self.docking = True
- self.docked = False
- self.OnExitSizeMove()
- event.Skip()
- elif self.firstShow:
- self.firstShow = False
-
- self.wasDocked = False
-
-
-
- def create_timer(self):
- self.timer = PyTimer(self.OnTimer)
-
-
- def SetEnabled(self, val):
- if not isinstance(val, bool):
- raise TypeError('Enabled must be a boolean')
-
- self._enabled = val
- if not val and self.docked:
- self.Undock()
- p = self.dockedRect[:2]
- self.docking = self.docked = self.autohidden = False
- wx.CallLater(50, self.SetRectSimple, wx.Rect(p[0], p[1], *wx.Size(*self.oldSize)))
- self.UpdateTaskbar()
- elif val and not (self.docked) and self.win.IsShownOnScreen():
- self.docking = False
- if self.OnMoving():
- self.OnExitSizeMove()
- if self.AutoHide:
- self.timer.Start(AUTOHIDE_TIMER_MS)
- self.motiontrigger = False
-
- self.win.SetRect(self.dockedRect)
-
- elif self.wasDocked:
- SetToolStyle(self.win, val)
- self.bypassMoveEvents = True
- if val:
- self.win.Rect = self.dockedRect
- else:
- self.win.Rect = wx.RectPS(self.dockedRect.Position, self.oldSize)
- self.bypassMoveEvents = False
- self.UpdateTaskbar()
-
- if not val:
- self.oldSize = None
-
-
- Enabled = property((lambda self: self._enabled), SetEnabled, None, 'Set this boolean property to enable or disable docking')
-
- def SetAutoHide(self, val):
- log.debug('SetAutoHide')
- if self.Enabled and self.docked:
- self.Undock(setFrameStyle = False)
- self._autohide = val
- self.Dock(setFrameStyle = False)
- self.docking = True
- self.docked = False
- self.OnExitSizeMove()
- if not val:
- self.ComeBack()
-
- self.UpdateTaskbar()
- else:
- self._autohide = val
-
- AutoHide = property((lambda self: self._autohide), SetAutoHide, None, 'Set this boolean property to enable or disable autohiding.')
-
- def SetRectSimple(self, rect):
- self.bypassMoveEvents = True
- self.win.SetRect(rect)
- self.bypassMoveEvents = False
-
-
- def OnTimer(self, e = None):
- if not self.Enabled and self.AutoHide and self.docked:
- return None
-
- w = self.win
- mp = wx.GetMousePosition()
- if w and not (self.motiontrigger) and not w.IsActive():
- if not (any,)((lambda .0: for r in .0:
- r.Contains(mp))((lambda .0: for w in .0:
- w.ScreenRect)([
- w] + self.LinkedWindows))):
- self.GoAway()
-
-
-
-
- def GoAway(self, rect = None):
- log.debug('GoAway')
- w = self.win
- r = None if rect else monitor_rect(w)
- margin = 1
- if self.side == ABE_LEFT:
- x = (r.X - w.Rect.width) + margin
- y = r.Y
- elif self.side == ABE_RIGHT:
- x = r.Right - margin
- y = r.Y
-
- self.motiontrigger = True
- self.autohidden = True
- self.timer.Stop()
- self.OnHide()
- self.AnimateWindowTo(wx.Rect(x, y, *w.Size))
-
-
- def ComeBack(self):
- log.debug('ComeBack')
- self.motiontrigger = False
- self.AnimateWindowTo(self.dockedRect)
- self.autohidden = False
- self.timer.Start(AUTOHIDE_TIMER_MS)
-
-
- def SetVelocity(self, v):
- self._velocity = v
-
- velocity = property((lambda self: self._velocity), SetVelocity)
- animateToTarget = None
- lasttick = None
-
- def AnimateWindowTo(self, r = None):
- now = default_timer()
- if r is not None:
- self.animateToTarget = r
- self.lasttick = now
-
- (targetx, y) = self.animateToTarget[:2]
- win = self.win
- winx = win.Position.x
- direction = sign(targetx - win.Position.x)
- delta = int((now - self.lasttick) * self.velocity) * direction
- self.bypassMoveEvents = True
- if winx != targetx and self.Animate:
- if delta:
- newx = winx + delta
- if (targetx >= winx) != (targetx >= newx):
- newx = targetx
-
- win.Move((newx, y))
- self.lasttick = now
-
- wx.CallLater(15, self.AnimateWindowTo)
- elif winx != targetx:
- win.SetRect(r)
-
- self.bypassMoveEvents = False
-
-
- def OnClose(self, e):
- log.info('OnClose: %r', e.EventObject)
- if self.Enabled and self.docked:
- if self.AutoHide:
- return self.GoAway()
- else:
- SHAppBarMessage(ABM_REMOVE, self.newAppBarData)
-
- e.Skip(True)
-
-
- def OnActivate(self, e):
- if not (self.Enabled) and not (self.AutoHide) and not (self.docked) or not (self.autohidden):
- return None
-
- if e.GetActive():
- if not onscreen(*self.win.Position):
- self.ComeBack()
- self.win.Raise()
-
- else:
- self.timer.Start(AUTOHIDE_TIMER_MS)
- e.Skip()
-
-
- def OnSysCommand(self, hWnd, msg, wParam, lParam):
- if self.Enabled and self.docked:
- if msg == WM_SYSCOMMAND and wParam in (UNKNOWN_MAX_FLAG, SC_MINIMIZE, SC_MAXIMIZE):
- return False
-
-
-
-
- def autohidden_mouseover(self):
- if self.Enabled and self.autohidden and self.motiontrigger and wx.FindWindowAtPointer() is self.win:
- self.ComeBack()
-
-
-
- def OnNCHitTest(self, hWnd, msg, wParam, lParam):
- if self.Enabled and self.motiontrigger:
- ms = wx.GetMouseState()
- if ms.LeftDown():
- self.bypassSizeEvents = True
- elif self.bypassSizeEvents:
- self.bypassSizeEvents = False
-
-
- try:
- t = self.autohidden_timer
- except AttributeError:
- t = self.autohidden_timer = wx.PyTimer(self.autohidden_mouseover)
-
- if not t.IsRunning():
- t.StartOneShot(self.RevealDurationMs)
-
- elif self.Enabled and self.docked:
- hit = DefWindowProc(hWnd, msg, wParam, lParam)
- if (self.side == ABE_LEFT or hit in (HTLEFT, HTTOPLEFT, HTBOTTOMLEFT) or self.side == ABE_RIGHT) and hit in (HTRIGHT, HTTOPRIGHT, HTBOTTOMRIGHT):
- return False
-
-
-
-
- def OnExitSizeMove(self, hWnd = 0, msg = 0, wParam = 0, lParam = 0):
- log.debug('SC_SIZE: %s', SC_SIZE)
- log.debug('OnExitSizeMove %s %s %s', msg, wParam, lParam)
- if not self.Enabled:
- return None
-
- if self.docked and self.AutoHide:
- if self.bypassSizeEvents:
- ms = wx.GetMouseState()
- if not ms.LeftDown():
- self.bypassSizeEvents = False
-
- return False
-
-
- if self.docking and not (self.docked):
- self.docking = False
- self.docked = True
- self.AppBarQuerySetPos(set = True)
-
- if self.docked and not (self.AutoHide):
- abd = self.GetNewAppBarData()
- abd.rc = wxRectToRECT(self.dockedRect)
- SHAppBarMessage(ABM_SETPOS, abd)
-
- if not self.docked:
- self.oldSize = None
-
- self.UpdateTaskbar()
-
-
- def UpdateTaskbar(self):
- log.debug('UpdateTaskbar')
- ontaskbar = self.win.OnTaskbar
- if ontaskbar and self.docked:
- log.debug('Hide Task')
- self.win.OnTaskbar = False
- else:
- should = self.ShouldShowInTaskbar()
- if should and not ontaskbar and not (self.docked):
- log.debug('Show Task')
- self.win.OnTaskbar = True
-
-
-
- def OnSizing(self, hWnd, msg, wParam, lParam):
- log.debug('OnSizing')
- if not self.Enabled and self.docked:
- log.debug('Not docked')
- return None
-
-
- try:
- if self._Docker__sizing:
- return None
- except AttributeError:
- pass
-
- side = self.side
- if not (self.bypassSizeEvents):
- if (side == ABE_LEFT or wParam == WMSZ_RIGHT or side == ABE_RIGHT) and wParam == WMSZ_LEFT:
- log.debug('Docked sizing')
- r = wx.Rect.FromRECT(RECT.from_address(lParam))
- self._Docker__sizing = True
- self.dockedRect = r
- self.oldSize.width = r.width
- self._Docker__sizing = False
- else:
- log.debug('Resize restricted')
- d = self.dockedRect
- r = RECT.from_address(lParam)
- r.x = d.x
- r.y = d.y
- r.right = d.x + d.width
- r.bottom = d.y + d.height
- return False
-
-
- def OnWindowPosChanging(self, hWnd, msg, wParam, lParam):
- if not self.Enabled:
- return None
- elif not self.bypassMoveEvents:
- mon = monitor_rect(self.win)
- margin = self.DockMargin
- pos = cast(lParam, POINTER(c_int))
- (x, y, w, h) = pos[2:6]
- if self.docked or self.docking:
- if not self.side == ABE_LEFT or x > mon.X + margin:
- pass
- awayFromLeft = x + w < mon.X
- if not self.side == ABE_RIGHT or x + w < mon.Right - margin:
- pass
- awayFromRight = x > mon.Right
- notResized = y + h != self.dockedRect.Bottom + 1
- if (awayFromLeft or awayFromRight) and notResized:
- return None
-
- for i, j in enumerate(xrange(2, 6)):
- pos[j] = self.dockedRect[i]
-
- elif self.oldSize:
- pos[4] = self.oldSize.width
- pos[5] = self.oldSize.height
-
-
-
-
- def OnMoving(self, e = None):
- if e:
- e.Skip(True)
-
- if not self.Enabled:
- return None
-
- log.debug('OnMoving')
- pos = self.win.Rect
- margin = self.DockMargin
- rect = monitor_rect(self.win)
- if not (self.docked) and not (self.docking):
- if pos.Right > rect.Right - margin and pos.x < rect.Right:
- isOnScreen = isRectOnScreen(wx.Rect(rect.Right + 1, rect.Top, 1, rect.Height))
- if not (self.AutoHide) or not isOnScreen:
- return self.Dock(ABE_RIGHT)
-
- elif pos.x < rect.X + margin and pos.Right > rect.X:
- isOnScreen = isRectOnScreen(wx.Rect(rect.X - 1, rect.Top, 1, rect.Height))
- if not (self.AutoHide) or not isOnScreen:
- return self.Dock(ABE_LEFT)
-
-
- elif self.side == ABE_LEFT or pos.x > rect.X + margin or pos.Right < rect.X:
- self.Undock()
- elif self.side == ABE_RIGHT or pos.Right < rect.Right - margin or pos.x > rect.Right:
- self.Undock()
-
-
-
- def Dock(self, side = None, setFrameStyle = True):
- log.debug('Dock')
- self.monId = Monitor.GetFromWindow(self.win).DeviceId
- if side is not None:
- self.side = side
-
- if self.AutoHide:
- if SHAppBarMessage(ABM_SETAUTOHIDEBAR, self.GetNewAppBarData(True)):
- log.info('registered autohide %s', sideStrings[self.side])
- if setFrameStyle:
- SetToolStyle(self.win, True)
-
- self.SetWinAlwaysOnTop(True)
- if self.oldSize is None:
- self.oldSize = self.win.Size
-
- self.SetAutoHidePos()
- self.timer.Start(AUTOHIDE_TIMER_MS)
- self.autohidden = False
- self.OnDock(True)
- return True
- else:
- log.warning('obtaining autohide bar failed')
-
- if SHAppBarMessage(ABM_NEW, self.newAppBarData):
- if not self.oldSize:
- pass
- self.oldSize = self.win.Size
- if setFrameStyle:
- SetToolStyle(self.win, True)
-
- self.AppBarQuerySetPos(set = False)
- self.OnDock(True)
- return True
-
-
-
- def Undock(self, setFrameStyle = True):
- log.debug('Undock')
- if setFrameStyle:
- SetToolStyle(self.win, False)
-
- if self.AutoHide:
- SHAppBarMessage(ABM_SETAUTOHIDEBAR, self.newAppBarData)
-
- SHAppBarMessage(ABM_REMOVE, self.newAppBarData)
- self.docking = self.docked = False
- self.OnDock(False)
- self.autohidden = False
- self.SetWinAlwaysOnTop()
-
- winPosArgs = (0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE)
-
- def OnAppBarStateChange(self, wParam, lParam):
- log.info('OnAppBarStateChange')
- state = SHAppBarMessage(ABM_GETSTATE, self.newAppBarData)
- None(SetWindowPos, self.Handle if ABS_ALWAYSONTOP & state else HWND_BOTTOM, *self.winPosArgs)
-
-
- def OnAppBarFullscreenApp(self, wParam, lParam):
- log.info('OnAppBarFullscreenApp')
- state = SHAppBarMessage(ABM_GETSTATE, self.newAppBarData)
- if lParam:
- None(SetWindowPos, self.Handle if ABS_ALWAYSONTOP & state else HWND_BOTTOM, *self.winPosArgs)
- elif state & ABS_ALWAYSONTOP:
- SetWindowPos(self.Handle, HWND_TOPMOST, *self.winPosArgs)
-
-
-
- def OnAppBarPosChanged(self, wParam, lParam):
- log.info('OnAppBarPosChanged')
- rc = RECT()
- mon = monitor_rect(self.win)
- rc.top = mon.Top
- rc.left = mon.Left
- rc.right = mon.Right
- rc.bottom = mon.Bototm
- winrect = self.win.Rect
- iHeight = winrect.Bottom - winrect.Top
- iWidth = winrect.Right - winrect.Left
- if self.side == ABE_TOP:
- rc.bottom = rc.top + iHeight
- elif self.side == ABE_BOTTOM:
- rc.top = rc.bottom - iHeight
- elif self.side == ABE_LEFT:
- rc.right = rc.left + iWidth
- elif self.side == ABE_RIGHT:
- rc.left = rc.right - iWidth
-
-
-
- def GetDockRect(self, rect = None):
- abd = self.newAppBarData
- mon = monitor_rect(self.win)
- if self.side in (ABE_LEFT, ABE_RIGHT):
- r = None if rect is None else rect
- winWidth = r.Width
- abd.rc.left = None if self.side == ABE_LEFT else (mon.Right - r.Width) + 1
- abd.rc.right = None if self.side == ABE_LEFT else mon.Right + 1
-
- abd.rc.top = mon.Top
- abd.rc.bottom = mon.Bottom + 1
- return (abd, winWidth)
-
-
- def SetAutoHidePos(self):
- (abd, unused_winWidth) = self.GetDockRect()
- rc = abd.rc
- self.dockedRect = wx.Rect(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top)
- self.docking = True
-
-
- def AppBarQuerySetPos(self, set = True):
- side = self.side
- (appBarData, winWidth) = self.GetDockRect()
- if not set:
- SHAppBarMessage(ABM_QUERYPOS, appBarData)
-
- if side == ABE_LEFT:
- appBarData.rc.right = appBarData.rc.left + winWidth
- elif side == ABE_RIGHT:
- appBarData.rc.left = appBarData.rc.right - winWidth
-
- if set:
- SHAppBarMessage(ABM_SETPOS, appBarData)
-
- rc = appBarData.rc
- self.dockedRect = wx.Rect(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top)
- self.docking = True
-
-
- def OnAppBarWindowArrange(self, wParam, lParam):
- log.info('OnAppBarWindowArrange')
-
- appBarCallbackMap = {
- ABN_STATECHANGE: OnAppBarStateChange,
- ABN_FULLSCREENAPP: OnAppBarFullscreenApp,
- ABN_POSCHANGED: OnAppBarPosChanged,
- ABN_WINDOWARRANGE: OnAppBarWindowArrange }
-
- def AppBarCallback(self, *params):
- log.info('AppBarCallback %r', params)
- (wParam, lParam) = params[2:4]
- self.appBarCallbackMap[wParam](wParam, lParam)
-
-
- def GetNewAppBarData(self, lParam = False):
- abd = APPBARDATA()
- abd.hWnd = self.Handle
- abd.uEdge = self.side
- abd.rc = self.win.RECT
- abd.lParam = lParam
- return abd
-
- newAppBarData = property(GetNewAppBarData)
-
- def Handle(self):
- return self.win.Handle
-
- Handle = property(Handle)
-
- def SetWinAlwaysOnTop(self, val = None):
- if self.ShouldAlwaysStayOnTop:
- self.ShouldAlwaysStayOnTop(val)
-
-
-
-
- def SetToolStyle(win, val):
- if val:
- win.SetWindowStyle(wx.FRAME_TOOL_WINDOW | win.GetWindowStyle())
- else:
- win.SetWindowStyle(~(wx.FRAME_TOOL_WINDOW) & win.GetWindowStyle())
-
-
- def monitor_rect(win):
- return Monitor.GetFromWindow(win).ClientArea
-
-
- def onscreen(x, y):
- return Monitor.GetFromPoint((x, y), find_near = False) is not None
-
-
- def isRectOnScreen(rect):
- return Monitor.GetFromRect(rect, find_near = False) is not None
-
-
- class APPBARDATA(Structure):
- _fields_ = [
- ('cbSize', DWORD),
- ('hWnd', HANDLE),
- ('uCallbackMessage', c_uint),
- ('uEdge', c_uint),
- ('rc', RECT),
- ('lParam', LPARAM)]
-
- taskbar_abd = APPBARDATA()
- from ctypes import sizeof
- taskbar_abd.cbSize = sizeof(APPBARDATA)
-
- def taskbar_info():
- uState = SHAppBarMessage(ABM_GETSTATE, taskbar_abd)
- return dict(always_on_top = uState & ABS_ALWAYSONTOP, autohide = uState & ABS_AUTOHIDE)
-
-
- try:
- import psyco
- except Exception:
- e = None
-
- psyco.bind(Docker)
-