{IrcClient,IrcMiRCARTBot.py,MiRC{2png,ART}}.py: include parameters in function header comments.

This commit is contained in:
Lucio Andrés Illanes Albornoz 2018-01-06 01:44:45 +01:00
parent 845185f9c3
commit 44e593714d
4 changed files with 69 additions and 70 deletions

View File

@ -32,13 +32,13 @@ class IrcClient:
clientSocket = clientSocketFile = None;
clientNextTimeout = None; clientQueue = None;
# {{{ close(): Close connection to server
# {{{ close(self): Close connection to server
def close(self):
if self.clientSocket != None:
self.clientSocket.close()
self.clientSocket = self.clientSocketFile = None;
# }}}
# {{{ connect(): Connect to server and register w/ optional timeout
# {{{ connect(self, timeout=None): Connect to server and register w/ optional timeout
def connect(self, timeout=None):
self.clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.clientSocket.setblocking(0)
@ -58,7 +58,7 @@ class IrcClient:
self.queue("USER", self.clientIdent, "0", "0", self.clientGecos)
return True
# }}}
# {{{ readline(): Read and parse single line from server into canonicalised list, honouring timers
# {{{ readline(self): Read and parse single line from server into canonicalised list, honouring timers
def readline(self):
if self.clientNextTimeout:
timeNow = time.time()
@ -87,7 +87,7 @@ class IrcClient:
msg = [""] + msg[0:]
return msg
# }}}
# {{{ queue(): Parse and queue single line to server from list
# {{{ queue(self, *args): Parse and queue single line to server from list
def queue(self, *args):
msg = ""; argNumMax = len(args);
for argNum in range(0, argNumMax):
@ -97,7 +97,7 @@ class IrcClient:
msg += args[argNum] + " "
self.clientQueue.append((msg + "\r\n").encode())
# }}}
# {{{ unqueue(): Send all queued lines to server, honouring timers
# {{{ unqueue(self): Send all queued lines to server, honouring timers
def unqueue(self):
while self.clientQueue:
msg = self.clientQueue[0]; msgLen = len(msg); msgBytesSent = 0;
@ -118,7 +118,7 @@ class IrcClient:
# }}}
#
# Initialisation method
# __init__(self, serverHname, serverPort, clientNick, clientIdent, clientGecos): initialisation method
def __init__(self, serverHname, serverPort, clientNick, clientIdent, clientGecos):
self.serverHname = serverHname; self.serverPort = serverPort;
self.clientNick = clientNick; self.clientIdent = clientIdent; self.clientGecos = clientGecos;

View File

@ -33,17 +33,17 @@ class IrcMiRCARTBot(IrcClient.IrcClient):
clientChannelLastMessage = clientChannelOps = clientChannel = None
clientChannelRejoin = None
# {{{ ContentTooLargeException: Raised by _urlretrieveReportHook() given download size > 1 MB
# {{{ ContentTooLargeException(Exception): Raised by _urlretrieveReportHook() given download size > 1 MB
class ContentTooLargeException(Exception):
pass
# }}}
# {{{ _dispatch001(): Dispatch single 001 (RPL_WELCOME)
# {{{ _dispatch001(self, message): Dispatch single 001 (RPL_WELCOME)
def _dispatch001(self, message):
self._log("Registered on {}:{} as {}, {}, {}.".format(self.serverHname, self.serverPort, self.clientNick, self.clientIdent, self.clientGecos))
self._log("Attempting to join {} on {}:{}...".format(self.clientChannel, self.serverHname, self.serverPort))
self.queue("JOIN", self.clientChannel)
# }}}
# {{{ _dispatch353(): Dispatch single 353 (RPL_NAMREPLY)
# {{{ _dispatch353(self, message): Dispatch single 353 (RPL_NAMREPLY)
def _dispatch353(self, message):
if message[4].lower() == self.clientChannel.lower():
for channelNickSpec in message[5].split(" "):
@ -53,19 +53,19 @@ class IrcMiRCARTBot(IrcClient.IrcClient):
self.clientChannelOps.append(channelNickSpec[1:].lower())
self._log("Authorising {} on {}".format(channelNickSpec[1:].lower(), message[4].lower()))
# }}}
# {{{ _dispatchJoin(): Dispatch single JOIN message from server
# {{{ _dispatchJoin(self, message): Dispatch single JOIN message from server
def _dispatchJoin(self, message):
self._log("Joined {} on {}:{}.".format(message[2].lower(), self.serverHname, self.serverPort))
self.clientNextTimeout = None; self.clientChannelRejoin = False;
# }}}
# {{{ _dispatchKick(): Dispatch single KICK message from server
# {{{ _dispatchKick(self, message): Dispatch single KICK message from server
def _dispatchKick(self, message):
if message[2].lower() == self.clientChannel.lower() \
and message[3].lower() == self.clientNick.lower():
self._log("Kicked from {} by {}, rejoining in 15 seconds".format(message[2].lower(), message[0]))
self.clientNextTimeout = time.time() + 15; self.clientChannelRejoin = True;
# }}}
# {{{ _dispatchMode(): Dispatch single MODE message from server
# {{{ _dispatchMode(self, message): Dispatch single MODE message from server
def _dispatchMode(self, message):
if message[2].lower() == self.clientChannel.lower():
channelModeType = "+"; channelModeArg = 4;
@ -93,16 +93,16 @@ class IrcMiRCARTBot(IrcClient.IrcClient):
self._log("Deauthorising {} on {}".format(channelAuthDel, message[2].lower()))
self.clientChannelOps.remove(channelAuthDel)
# }}}
# {{{ _dispatchNone(): Dispatch None message from server
# {{{ _dispatchNone(self): Dispatch None message from server
def _dispatchNone(self):
self._log("Disconnected from {}:{}.".format(self.serverHname, self.serverPort))
self.close()
# }}}
# {{{ _dispatchPing(): Dispatch single PING message from server
# {{{ _dispatchPing(self, message): Dispatch single PING message from server
def _dispatchPing(self, message):
self.queue("PONG", message[2])
# }}}
# {{{ _dispatchPrivmsg(): Dispatch single PRIVMSG message from server
# {{{ _dispatchPrivmsg(self, message): Dispatch single PRIVMSG message from server
def _dispatchPrivmsg(self, message):
if message[2].lower() == self.clientChannel.lower() \
and message[3].startswith("!pngbot "):
@ -152,18 +152,18 @@ class IrcMiRCARTBot(IrcClient.IrcClient):
if os.path.isfile(imgTmpFilePath):
os.remove(imgTmpFilePath)
# }}}
# {{{ _dispatchTimer(): Dispatch single client timer expiration
# {{{ _dispatchTimer(self): Dispatch single client timer expiration
def _dispatchTimer(self):
if self.clientChannelRejoin:
self._log("Attempting to join {} on {}:{}...".format(self.clientChannel, self.serverHname, self.serverPort))
self.queue("JOIN", self.clientChannel)
self.clientNextTimeout = time.time() + 15; self.clientChannelRejoin = True;
# }}}
# {{{ _log(): Log single message to stdout w/ timestamp
# {{{ _log(self, msg): Log single message to stdout w/ timestamp
def _log(self, msg):
print(time.strftime("%Y/%m/%d %H:%M:%S") + " " + msg)
# }}}
# {{{ _uploadToImgur(): Upload single file to Imgur
# {{{ _uploadToImgur(self, imgFilePath, imgName, imgTitle, apiKey): Upload single file to Imgur
def _uploadToImgur(self, imgFilePath, imgName, imgTitle, apiKey):
requestImageData = open(imgFilePath, "rb").read()
requestData = { \
@ -181,12 +181,12 @@ class IrcMiRCARTBot(IrcClient.IrcClient):
else:
return [responseHttp.status_code]
# }}}
# {{{ _urlretrieveReportHook(): Limit downloads to 1 MB
# {{{ _urlretrieveReportHook(count, blockSize, totalSize): Limit downloads to 1 MB
def _urlretrieveReportHook(count, blockSize, totalSize):
if (totalSize > pow(2,20)):
raise IrcMiRCARTBot.ContentTooLargeException
# }}}
# {{{ connect(): Connect to server and (re)initialise w/ optional timeout
# {{{ connect(self, timeout=None): Connect to server and (re)initialise w/ optional timeout
def connect(self, timeout=None):
self._log("Connecting to {}:{}...".format(self.serverHname, self.serverPort))
if super().connect(timeout):
@ -198,7 +198,7 @@ class IrcMiRCARTBot(IrcClient.IrcClient):
else:
return False
# }}}
# {{{ dispatch(): Read, parse, and dispatch single line from server
# {{{ dispatch(self): Read, parse, and dispatch single line from server
def dispatch(self):
while True:
if self.clientNextTimeout:
@ -228,7 +228,7 @@ class IrcMiRCARTBot(IrcClient.IrcClient):
# }}}
#
# Initialisation method
# __init__(self, serverHname, serverPort="6667", clientNick="pngbot", clientIdent="pngbot", clientGecos="pngbot", clientChannel="#MiRCART"): initialisation method
def __init__(self, serverHname, serverPort="6667", clientNick="pngbot", clientIdent="pngbot", clientGecos="pngbot", clientChannel="#MiRCART"):
super().__init__(serverHname, serverPort, clientNick, clientIdent, clientGecos)
self.clientChannel = clientChannel

View File

@ -81,7 +81,7 @@ class MiRC2png:
(187, 187, 187, 255), # Light Grey
]
# }}}
# {{{ _State: Parsing loop state
# {{{ _State(Enum): Parsing loop state
class _State(Enum):
STATE_CHAR = 1
STATE_COLOUR_SPEC = 2
@ -89,15 +89,15 @@ class MiRC2png:
STATE_CSPEC_DIGIT1 = 3
# }}}
# {{{ _countChar(): XXX
# {{{ _countChar(self, char): XXX
def _countChar(self, char):
return True
# }}}
# {{{ _countColourSpecState(): XXX
# {{{ _countColourSpecState(self, colourSpec): XXX
def _countColourSpecState(self, colourSpec):
return 0
# }}}
# {{{ _render(): XXX
# {{{ _render(self): XXX
def _render(self):
self.outCurX = 0; self.outCurY = 0;
for inCurRow in range(0, len(self.inLines)):
@ -116,7 +116,7 @@ class MiRC2png:
self._syncColourSpecState)
self.outCurX = 0; self.outCurY += self.outImgFontSize[1];
# }}}
# {{{ _getMaxCols(): Calculate widest row in lines, ignoring non-printable & mIRC control code sequences
# {{{ _getMaxCols(self, lines): Calculate widest row in lines, ignoring non-printable & mIRC control code sequences
def _getMaxCols(self, lines):
maxCols = 0;
for inCurRow in range(0, len(lines)):
@ -136,7 +136,7 @@ class MiRC2png:
maxCols = max(maxCols, curRowCols)
return maxCols
# }}}
# {{{ _parseAsChar(): Parse single character as regular character and mutate state
# {{{ _parseAsChar(self, char, fn): Parse single character as regular character and mutate state
def _parseAsChar(self, char, fn):
if char == "":
self._State = self._State.STATE_CSPEC_DIGIT0; self.inCurCol += 1;
@ -144,7 +144,7 @@ class MiRC2png:
else:
self.inCurCol += 1; return fn(char);
# }}}
# {{{ _parseAsColourSpec(): Parse single character as mIRC colour control code sequence and mutate state
# {{{ _parseAsColourSpec(self, char, fn): Parse single character as mIRC colour control code sequence and mutate state
def _parseAsColourSpec(self, char, fn):
if self._State == self._State.STATE_CSPEC_DIGIT0 \
and char == ",":
@ -170,7 +170,7 @@ class MiRC2png:
self.inCurDigits = 0
return [True, result]
# }}}
# {{{ _syncChar(): XXX
# {{{ _syncChar(self, char): XXX
def _syncChar(self, char):
if char == "":
self.inCurBold = 0 if self.inCurBold else 1;
@ -207,7 +207,7 @@ class MiRC2png:
self.outCurX += self.outImgFontSize[0];
return True
# }}}
# {{{ _syncColourSpecState(): XXX
# {{{ _syncColourSpecState(self, colourSpec): XXX
def _syncColourSpecState(self, colourSpec):
if len(colourSpec) > 0:
colourSpec = colourSpec.split(",")
@ -222,7 +222,7 @@ class MiRC2png:
# }}}
#
# Initialisation method
# __init__(self, inFilePath, imgFilePath, fontFilePath="DejaVuSansMono.ttf", fontSize=11): initialisation method
def __init__(self, inFilePath, imgFilePath, fontFilePath="DejaVuSansMono.ttf", fontSize=11):
self.inFilePath = inFilePath; self.inFile = open(inFilePath, "r");
self.inLines = self.inFile.readlines()

View File

@ -55,7 +55,7 @@ class MiRCARTCanvas(wx.Panel):
mircBg = mircFg = mircBrushes = mircPens = None
patchesTmp = patchesUndo = patchesUndoLevel = None
# {{{ _drawPatch(): XXX
# {{{ _drawPatch(self, patch, eventDc, tmpDc, atX, atY): XXX
def _drawPatch(self, patch, eventDc, tmpDc, atX, atY):
patchXabs = (atX + patch[0]) * self.getCellWidth()
patchYabs = (atY + patch[1]) * self.getCellHeight()
@ -67,17 +67,17 @@ class MiRCARTCanvas(wx.Panel):
dc.DrawRectangle(patchXabs, patchYabs, \
self.getCellWidth(), self.getCellHeight())
# }}}
# {{{ _eventPointToMapX(): XXX
# {{{ _eventPointToMapX(self, eventPoint): XXX
def _eventPointToMapX(self, eventPoint):
rectX = eventPoint.x - (eventPoint.x % self.getCellWidth())
return int(rectX / self.getCellWidth() if rectX else 0)
# }}}
# {{{ _eventPointToMapY(): XXX
# {{{ _eventPointToMapY(self, eventPoint): XXX
def _eventPointToMapY(self, eventPoint):
rectY = eventPoint.y - (eventPoint.y % self.getCellHeight())
return int(rectY / self.getCellHeight() if rectY else 0)
# }}}
# {{{ _onMouseEvent(): XXX
# {{{ _onMouseEvent(self, event): XXX
def _onMouseEvent(self, event):
eventObject = event.GetEventObject()
eventDc = wx.ClientDC(self); tmpDc = wx.MemoryDC();
@ -92,7 +92,7 @@ class MiRCARTCanvas(wx.Panel):
mapPatches = tool.onMouseDown(event, mapX, mapY, event.LeftIsDown(), event.RightIsDown())
self._processMapPatches(mapPatches, eventDc, tmpDc, mapX, mapY)
# }}}
# {{{ _processMapPatches(): XXX
# {{{ _processMapPatches(self, mapPatches, eventDc, tmpDc, atX, atY): XXX
def _processMapPatches(self, mapPatches, eventDc, tmpDc, atX, atY):
for mapPatch in mapPatches:
mapPatchTmp = mapPatch[0]; mapPatchW = mapPatch[1]; mapPatchH = mapPatch[2];
@ -122,58 +122,58 @@ class MiRCARTCanvas(wx.Panel):
if len(mapPatch[3]):
self.parentFrame.onCanvasUpdate()
# }}}
# {{{ getBackgroundColour(): XXX
# {{{ getBackgroundColour(self): XXX
def getBackgroundColour(self):
return self.mircBg
# }}}
# {{{ getCellHeight(): XXX
# {{{ getCellHeight(self): XXX
def getCellHeight(self):
return self.cellSize[1]
# }}}
# {{{ getCellWidth(): XXX
# {{{ getCellWidth(self): XXX
def getCellWidth(self):
return self.cellSize[0]
# }}}
# {{{ getForegroundColour(): XXX
# {{{ getForegroundColour(self): XXX
def getForegroundColour(self):
return self.mircFg
# }}}
# {{{ getHeight(): XXX
# {{{ getHeight(self): XXX
def getHeight(self):
return self.canvasSize[1]
# }}}
# {{{ getMap(): XXX
# {{{ getMap(self): XXX
def getMap(self):
return self.canvasMap
# }}}
# {{{ getWidth(): XXX
# {{{ getWidth(self): XXX
def getWidth(self):
return self.canvasSize[0]
# }}}
# {{{ onLeftDown(): XXX
# {{{ onLeftDown(self, event): XXX
def onLeftDown(self, event):
self._onMouseEvent(event)
# }}}
# {{{ onMotion(): XXX
# {{{ onMotion(self, event): XXX
def onMotion(self, event):
self._onMouseEvent(event)
# }}}
# {{{ onPaint(): XXX
# {{{ onPaint(self, event): XXX
def onPaint(self, event):
eventDc = wx.BufferedPaintDC(self, self.canvasBitmap)
# }}}
# {{{ onPaletteEvent(): XXX
# {{{ onPaletteEvent(self, leftDown, rightDown, numColour): XXX
def onPaletteEvent(self, leftDown, rightDown, numColour):
if leftDown:
self.mircFg = numColour
elif rightDown:
self.mircBg = numColour
# }}}
# {{{ onRightDown(): XXX
# {{{ onRightDown(self, event): XXX
def onRightDown(self, event):
self._onMouseEvent(event)
# }}}
# {{{ redo(): XXX
# {{{ redo(self): XXX
def redo(self):
if self.patchesUndoLevel > 0:
self.patchesUndoLevel -= 1
@ -188,7 +188,7 @@ class MiRCARTCanvas(wx.Panel):
else:
return False
# }}}
# {{{ undo(): XXX
# {{{ undo(self): XXX
def undo(self):
if self.patchesUndo[self.patchesUndoLevel] != None:
undoPatch = self.patchesUndo[self.patchesUndoLevel][0]
@ -203,7 +203,7 @@ class MiRCARTCanvas(wx.Panel):
else:
return False
# }}}
# {{{ Initialisation method
# {{{ __init__(self, parent, parentFrame, canvasPos, cellSize, canvasSize, canvasTools): Initialisation method
def __init__(self, parent, parentFrame, canvasPos, cellSize, canvasSize, canvasTools):
self.parentFrame = parentFrame
canvasWinSize = (cellSize[0] * canvasSize[0], cellSize[1] * canvasSize[1])
@ -239,15 +239,15 @@ class MiRCARTTool():
"""XXX"""
parentCanvas = None
# {{{ onMouseDown(): XXX
# {{{ onMouseDown(self, event, mapX, mapY, isLeftDown, isRightDown): XXX
def onMouseDown(self, event, mapX, mapY, isLeftDown, isRightDown):
pass
# }}}
# {{{ onMouseMotion(): XXX
# {{{ onMouseMotion(self, event, mapX, mapY, isLeftDown, isRightDown): XXX
def onMouseMotion(self, event, mapX, mapY, isLeftDown, isRightDown):
pass
# }}}
# {{{ Initialisation method
# {{{ __init__(self, parentCanvas): initialisation method
def __init__(self, parentCanvas):
self.parentCanvas = parentCanvas
# }}}
@ -255,7 +255,7 @@ class MiRCARTTool():
class MiRCARTToolRect(MiRCARTTool):
"""XXX"""
# {{{ _draw(): XXX
# {{{ _draw(self, event, mapX, mapY, isLeftDown, isRightDown): XXX
def _draw(self, event, mapX, mapY, isLeftDown, isRightDown):
if isLeftDown:
return [[False, 1, 1, [[0, 0, \
@ -276,15 +276,15 @@ class MiRCARTToolRect(MiRCARTTool):
self.parentCanvas.getForegroundColour(), \
self.parentCanvas.getForegroundColour(), " "]]]]
# }}}
# {{{ onMouseDown(): XXX
# {{{ onMouseDown(self, event, mapX, mapY, isLeftDown, isRightDown): XXX
def onMouseDown(self, event, mapX, mapY, isLeftDown, isRightDown):
return self._draw(event, mapX, mapY, isLeftDown, isRightDown)
# }}}
# {{{ onMouseMotion(): XXX
# {{{ onMouseMotion(self, event, mapX, mapY, isLeftDown, isRightDown): XXX
def onMouseMotion(self, event, mapX, mapY, isLeftDown, isRightDown):
return self._draw(event, mapX, mapY, isLeftDown, isRightDown)
# }}}
# {{{ Initialisation method
# {{{ __init__(self, parentCanvas): initialisation method
def __init__(self, parentCanvas):
super().__init__(parentCanvas)
# }}}
@ -292,8 +292,7 @@ class MiRCARTToolRect(MiRCARTTool):
class MiRCARTFrame(wx.Frame):
"""XXX"""
panelSkin = panelCanvas = None
menuItemsById = menuBar = toolBar = accelTable = None
statusBar = None
menuItemsById = menuBar = toolBar = accelTable = statusBar = None
# {{{ Types
TID_COMMAND = (0x001)
@ -372,7 +371,7 @@ class MiRCARTFrame(wx.Frame):
AID_EDIT = (0x500, TID_ACCELS, (CID_UNDO, CID_REDO))
# }}}
# {{{ _drawIcon(): XXX
# {{{ _drawIcon(self, solidColour): XXX
def _drawIcon(self, solidColour):
iconBitmap = wx.Bitmap((16,16))
iconDc = wx.MemoryDC(); iconDc.SelectObject(iconBitmap);
@ -382,7 +381,7 @@ class MiRCARTFrame(wx.Frame):
iconDc.DrawRectangle(0, 0, 16, 16)
return iconBitmap
# }}}
# {{{ _initAccelTable(): XXX
# {{{ _initAccelTable(self, accelsDescr, handler): XXX
def _initAccelTable(self, accelsDescr, handler):
accelTableEntries = [wx.AcceleratorEntry() for n in range(0, len(accelsDescr[2]))]
for numAccel in range(0, len(accelsDescr[2])):
@ -392,7 +391,7 @@ class MiRCARTFrame(wx.Frame):
self.Bind(wx.EVT_MENU, handler, id=accelDescr[0])
return accelTableEntries
# }}}
# {{{ _initMenus(): XXX
# {{{ _initMenus(self, menuBar, menusDescr, handler): XXX
def _initMenus(self, menuBar, menusDescr, handler):
for menuDescr in menusDescr:
menuWindow = wx.Menu()
@ -405,7 +404,7 @@ class MiRCARTFrame(wx.Frame):
self.Bind(wx.EVT_MENU, handler, menuItemWindow)
menuBar.Append(menuWindow, menuDescr[3])
# }}}
# {{{ _initToolBars(): XXX
# {{{ _initToolBars(self, toolBar, toolBarsDescr, handler): XXX
def _initToolBars(self, toolBar, toolBarsDescr, handler):
for toolBarDescr in toolBarsDescr:
for toolBarItem in toolBarDescr[2]:
@ -426,7 +425,7 @@ class MiRCARTFrame(wx.Frame):
self.Bind(wx.EVT_TOOL, handler, toolBarItemWindow)
self.Bind(wx.EVT_TOOL_RCLICKED, handler, toolBarItemWindow)
# }}}
# {{{ _saveAs(): XXX
# {{{ _saveAs(self, pathName): XXX
def _saveAs(self, pathName):
try:
with open(pathName, "w") as file:
@ -449,7 +448,7 @@ class MiRCARTFrame(wx.Frame):
except IOError as error:
return [False, error]
# }}}
# {{{ _updateStatusBar(): XXX
# {{{ _updateStatusBar(self): XXX
def _updateStatusBar(self):
text = "Foreground colour:"
text += " " + str(self.panelCanvas.getForegroundColour())
@ -459,7 +458,7 @@ class MiRCARTFrame(wx.Frame):
self.statusBar.SetStatusText(text)
# }}}
# {{{ onCanvasUpdate(): XXX
# {{{ onCanvasUpdate(self): XXX
def onCanvasUpdate(self):
if self.panelCanvas.patchesUndo[self.panelCanvas.patchesUndoLevel] != None:
self.menuItemsById[self.CID_UNDO[0]].Enable(True)
@ -470,7 +469,7 @@ class MiRCARTFrame(wx.Frame):
else:
self.menuItemsById[self.CID_REDO[0]].Enable(False)
# }}}
# {{{ onFrameCommand(): XXX
# {{{ onFrameCommand(self, event): XXX
def onFrameCommand(self, event):
cid = event.GetId()
if cid == self.CID_NEW[0]:
@ -526,7 +525,7 @@ class MiRCARTFrame(wx.Frame):
self.panelCanvas.onPaletteEvent(leftIsDown, rightIsDown, numColour)
self._updateStatusBar()
# }}}
# {{{ Initialisation method
# {{{ __init__(self, parent, appSize=(800, 600), canvasPos=(25, 50), cellSize=(7, 14), canvasSize=(80, 25)): initialisation method
def __init__(self, parent, appSize=(800, 600), canvasPos=(25, 50), cellSize=(7, 14), canvasSize=(80, 25)):
super().__init__(parent, wx.ID_ANY, "MiRCART", size=appSize)
self.panelSkin = wx.Panel(self, wx.ID_ANY)