@api.check(<NUM_LIT:1>, "<STR_LIT>")<EOL>def control_get_text_by_handle(hwnd, h_ctrl, **kwargs):

buf_size = kwargs.get("<STR_LIT>", <NUM_LIT>)<EOL>ctrl_text = ctypes.create_unicode_buffer(buf_size)<EOL>AUTO_IT.AU3_ControlGetTextByHandle(<EOL>HWND(hwnd), HWND(h_ctrl), ctrl_text, INT(buf_size)<EOL>)<EOL>return ctrl_text.value.rstrip()<EOL>


@api.check(<NUM_LIT:2>, "<STR_LIT>")<EOL>def control_hide(title, control, **kwargs):

text = kwargs.get("<STR_LIT:text>", "<STR_LIT>")<EOL>ret = AUTO_IT.AU3_ControlHide(<EOL>LPCWSTR(title), LPCWSTR(text), LPCWSTR(control))<EOL>return ret<EOL>

:param title:
:param control:
:param kwargs:
:return:


@api.check(<NUM_LIT:2>, "<STR_LIT>")<EOL>def control_hide_by_handle(hwnd, h_ctrl):

ret = AUTO_IT.AU3_ControlHideByHandle(HWND(hwnd), HWND(h_ctrl))<EOL>return ret<EOL>


@api.check(<NUM_LIT:2>, "<STR_LIT>")<EOL>def control_move(title, control, x, y, width=-<NUM_LIT:1>, height=-<NUM_LIT:1>, **kwargs):

text = kwargs.get("<STR_LIT:text>", "<STR_LIT>")<EOL>ret = AUTO_IT.AU3_ControlMove(<EOL>LPCWSTR(title), LPCWSTR(text), LPCWSTR(control),<EOL>INT(x), INT(y), INT(width), INT(height)<EOL>)<EOL>return ret<EOL>

:param title:
:param control:
:param x:
:param y:
:param kwargs:
:return:


@api.check(<NUM_LIT:2>, "<STR_LIT>")<EOL>def control_move_by_handle(hwnd, h_ctrl, x, y, width=-<NUM_LIT:1>, height=-<NUM_LIT:1>):

ret = AUTO_IT.AU3_ControlMoveByHandle(<EOL>HWND(hwnd), HWND(h_ctrl), INT(x), INT(y), INT(width), INT(height)<EOL>)<EOL>return ret<EOL>

:param hwnd:
:param h_ctrl:
:param x:
:param y:
:param width:
:param height:
:return:


@api.check(<NUM_LIT:2>, "<STR_LIT>")<EOL>def control_send(title, control, send_text, mode=<NUM_LIT:0>, **kwargs):

text = kwargs.get("<STR_LIT:text>", "<STR_LIT>")<EOL>ret = AUTO_IT.AU3_ControlSend(<EOL>LPCWSTR(title), LPCWSTR(text), LPCWSTR(control),<EOL>LPCWSTR(send_text), INT(mode)<EOL>)<EOL>return ret<EOL>

:param title:
:param control:
:param send_text:
:param mode:
flag = 0 (default), Text contains special characters like + to indicate
    SHIFT and {LEFT} to indicate left arrow.
flag = 1, keys are sent raw.
:param kwargs:
:return:


@api.check(<NUM_LIT:2>, "<STR_LIT>")<EOL>def control_send_by_handle(hwnd, h_ctrl, send_text, mode=<NUM_LIT:0>):

ret = AUTO_IT.AU3_ControlSendByHandle(<EOL>HWND(hwnd), HWND(h_ctrl), LPCWSTR(send_text), INT(mode)<EOL>)<EOL>return ret<EOL>

:param hwnd:
:param h_ctrl:
:param send_text:
:param mode:
:return:


@api.check(<NUM_LIT:2>, "<STR_LIT>")<EOL>def control_set_text(title, control, control_text, **kwargs):

text = kwargs.get("<STR_LIT:text>", "<STR_LIT>")<EOL>ret = AUTO_IT.AU3_ControlSetText(<EOL>LPCWSTR(title), LPCWSTR(text), LPCWSTR(control), LPCWSTR(control_text)<EOL>)<EOL>return ret<EOL>

:param title:
:param control:
:param control_text:
:param kwargs:
:return:


@api.check(<NUM_LIT:2>, "<STR_LIT>")<EOL>def control_set_text_by_handle(hwnd, h_ctrl, control_text):

ret = AUTO_IT.AU3_ControlSetTextByHandle(<EOL>HWND(hwnd), HWND(h_ctrl), LPCWSTR(control_text)<EOL>)<EOL>return ret<EOL>

:param hwnd:
:param h_ctrl:
:param control_text:
:return:


@api.check(<NUM_LIT:2>, "<STR_LIT>")<EOL>def control_show(title, control, **kwargs):

text = kwargs.get("<STR_LIT:text>", "<STR_LIT>")<EOL>ret = AUTO_IT.AU3_ControlShow(<EOL>LPCWSTR(title), LPCWSTR(text), LPCWSTR(control))<EOL>return ret<EOL>


@api.check(<NUM_LIT:2>, "<STR_LIT>")<EOL>def control_show_by_handle(hwnd, h_ctrl):

ret = AUTO_IT.AU3_ControlShowByHandle(HWND(hwnd), HWND(h_ctrl))<EOL>return ret<EOL>


@api.check(<NUM_LIT:1>, "<STR_LIT>")<EOL>def control_tree_view(title, control, command, **kwargs):

text = kwargs.get("<STR_LIT:text>", "<STR_LIT>")<EOL>buf_size = kwargs.get("<STR_LIT>", <NUM_LIT>)<EOL>result = ctypes.create_unicode_buffer(buf_size)<EOL>extra1 = kwargs.get("<STR_LIT>", "<STR_LIT>")<EOL>extra2 = kwargs.get("<STR_LIT>", "<STR_LIT>")<EOL>AUTO_IT.AU3_ControlTreeView(<EOL>LPCWSTR(title), LPCWSTR(text), LPCWSTR(control), LPCWSTR(command),<EOL>LPCWSTR(extra1), LPCWSTR(extra2), result, INT(buf_size)<EOL>)<EOL>return result.value.rstrip()<EOL>

:param title:
:param control:
:param command:
:param args:
:param kwargs:
:return:


@api.check(<NUM_LIT:1>, "<STR_LIT>")<EOL>def control_tree_view_by_handle(hwnd, h_ctrl, command, **kwargs):

extra1 = kwargs.get("<STR_LIT>", "<STR_LIT>")<EOL>extra2 = kwargs.get("<STR_LIT>", "<STR_LIT>")<EOL>buf_size = kwargs.get("<STR_LIT>", <NUM_LIT>)<EOL>result = ctypes.create_unicode_buffer(buf_size)<EOL>AUTO_IT.AU3_ControlTreeViewByHandle(<EOL>HWND(hwnd), HWND(h_ctrl), LPCWSTR(command),<EOL>LPCWSTR(extra1), LPCWSTR(extra2), result, INT(buf_size)<EOL>)<EOL>return result.value.rstrip()<EOL>

:param hwnd:
:param h_ctrl:
:param command:
:param kwargs:
:return:


@api.check(<NUM_LIT:1>, "<STR_LIT>")<EOL>def statusbar_get_text(title, text="<STR_LIT>", part=<NUM_LIT:1>, buf_size=<NUM_LIT>):

sb_text = ctypes.create_unicode_buffer(buf_size)<EOL>AUTO_IT.AU3_StatusbarGetText(<EOL>LPCWSTR(title), LPCWSTR(text), INT(part), sb_text, INT(buf_size)<EOL>)<EOL>return sb_text.value.rstrip()<EOL>

:param title:
:param text:
:param part: The "part" number of the status bar to read - the default
    is 1. 1 is the first possible part and usually the one that contains
    the useful messages like "Ready" "Loading...", etc.
:param buf_size:
:return:


@api.check(<NUM_LIT:1>, "<STR_LIT>")<EOL>def statusbar_get_text_by_handle(hwnd, part=<NUM_LIT:1>, buf_size=<NUM_LIT>):

statusbar_text = ctypes.create_unicode_buffer(buf_size)<EOL>AUTO_IT.AU3_StatusbarGetTextByHandle(<EOL>HWND(hwnd), INT(part), statusbar_text, INT(buf_size)<EOL>)<EOL>return statusbar_text.value.rstrip()<EOL>

:param hwnd:
:param part:
:param buf_size:
:return:


pre_value = AUTO_IT.AU3_AutoItSetOption(LPCWSTR(option), INT(param))<EOL>return pre_value<EOL>

Changes the operation of various AutoIt functions/parameters
:param option: The option to change
:param param: The parameter (varies by option).
:return:


clip = ctypes.create_unicode_buffer(buf_size)<EOL>AUTO_IT.AU3_ClipGet(clip, INT(buf_size))<EOL>return clip.value.rstrip()<EOL>


ret = AUTO_IT.AU3_ClipPut(LPCWSTR(value))<EOL>return ret<EOL>


ret = AUTO_IT.AU3_IsAdmin()<EOL>return ret<EOL>


def drive_map_add(device, share, flag=<NUM_LIT:0>, user="<STR_LIT>", pwd="<STR_LIT>", buf_size=<NUM_LIT>):

result = ctypes.create_unicode_buffer(buf_size)<EOL>err_code = {<EOL><NUM_LIT:1>: "<STR_LIT>",<EOL><NUM_LIT:2>: "<STR_LIT>",<EOL><NUM_LIT:3>: "<STR_LIT>",<EOL><NUM_LIT:4>: "<STR_LIT>",<EOL><NUM_LIT:5>: "<STR_LIT>",<EOL><NUM_LIT:6>: "<STR_LIT>"<EOL>}<EOL>AUTO_IT.AU3_DriveMapAdd(<EOL>LPCWSTR(device), LPCWSTR(share), INT(flag), LPCWSTR(user),<EOL>LPCWSTR(pwd), result, INT(buf_size))<EOL>if error():<EOL><INDENT>raise AutoItError(err_code.get(error(), None))<EOL><DEDENT>return result.value.rstrip()<EOL>

:param device:
:param share:
:param flag: 0 = default
    1 = Persistant mapping
    8 = Show authentication dialog if required
:param user:
:param pwd:
:param buf_size:
:return:


ret = AUTO_IT.AU3_DriveMapDel(LPCWSTR(device))<EOL>return ret<EOL>


@api.check(<NUM_LIT:1>, err_msg="<STR_LIT>")<EOL>def drive_map_get(device, buf_size=<NUM_LIT>):

mapping = ctypes.create_unicode_buffer(buf_size)<EOL>AUTO_IT.AU3_DriveMapGet(LPCWSTR(device), mapping, INT(buf_size))<EOL>return mapping.value.rstrip()<EOL>

:param device:
:param buf_size:
:return:


def mouse_click(button="<STR_LIT:left>", x=INTDEFAULT, y=INTDEFAULT, clicks=<NUM_LIT:1>, speed=-<NUM_LIT:1>):

ret = AUTO_IT.AU3_MouseClick(<EOL>LPCWSTR(button), INT(x), INT(y), INT(clicks), INT(speed)<EOL>)<EOL>return ret<EOL>

:param button:
:param x:
:param y:
:param clicks:
:param speed:
:return:


def mouse_click_drag(x1, y1, x2, y2, button="<STR_LIT:left>", speed=-<NUM_LIT:1>):

ret = AUTO_IT.AU3_MouseClickDrag(<EOL>LPCWSTR(button), INT(x1), INT(y1), INT(x2), INT(y2), INT(speed)<EOL>)<EOL>return ret<EOL>

:param x1:
:param y1:
:param x2:
:param y2:
:param button:
:param speed:
:return:


AUTO_IT.AU3_MouseDown(LPCWSTR(button))<EOL>


ret = AUTO_IT.AU3_MouseGetCursor()<EOL>return ret<EOL>


p = POINT()<EOL>AUTO_IT.AU3_MouseGetPos(ctypes.byref(p))<EOL>return p.x, p.y<EOL>


def mouse_move(x, y, speed=-<NUM_LIT:1>):

ret = AUTO_IT.AU3_MouseMove(INT(x), INT(y), INT(speed))<EOL>return ret<EOL>

:param x:
:param y:
:param speed:
:return:


AUTO_IT.AU3_MouseUp(LPCWSTR(button))<EOL>


@api.check(<NUM_LIT:1>, err_msg="<STR_LIT>")<EOL>def mouse_wheel(direction, clicks=-<NUM_LIT:1>):

AUTO_IT.AU3_MouseWheel(LPCWSTR(direction), INT(clicks))<EOL>

:param direction: "up" or "down"
:param clicks:
:return:


return auto_it_set_option(option, value)<EOL>


def pixel_checksum(left, top, right, bottom, step=<NUM_LIT:1>):

rect = RECT(left, top, right, bottom)<EOL>ret = AUTO_IT.AU3_PixelChecksum(ctypes.byref(rect), INT(step))<EOL>return ret<EOL>

:param left:
:param top:
:param right:
:param bottom:
:param step:
:return:


@api.check(<NUM_LIT:2>, unexpected_ret=(-<NUM_LIT:1>,), err_msg="<STR_LIT>")<EOL>def pixel_get_color(x, y):

ret = AUTO_IT.AU3_PixelGetColor(INT(x), INT(y))<EOL>return ret<EOL>


@api.check(<NUM_LIT:1>, err_msg="<STR_LIT>")<EOL>def pixel_search(left, top, right, bottom, col, var=<NUM_LIT:1>, step=<NUM_LIT:1>):

p = POINT()<EOL>rect = RECT(left, top, right, bottom)<EOL>AUTO_IT.AU3_PixelSearch(<EOL>ctypes.byref(rect), INT(col), INT(var), INT(step), ctypes.byref(p)<EOL>)<EOL>return p.x, p.y<EOL>

:param left:
:param top:
:param right:
:param bottom:
:param col:
:param var:
:param step:
:return:


AUTO_IT.AU3_Send(LPCWSTR(send_text), INT(mode))<EOL>

Sends simulated keystrokes to the active window.
:param send_text:
:param mode: Changes how "keys" is processed:
    flag = 0 (default), Text contains special characters like + and ! to
     indicate SHIFT and ALT key presses.
    flag = 1, keys are sent raw.
:return:


def tooltip(tip, x=INTDEFAULT, y=INTDEFAULT):

AUTO_IT.AU3_ToolTip(LPCWSTR(tip), INT(x), INT(y))<EOL>

:param tip:
:param x:
:param y:
:return:


def check(self, mark=<NUM_LIT:0>, err_msg="<STR_LIT>", **kwds):

unexpected_ret = kwds.get("<STR_LIT>", (<NUM_LIT:0>,))<EOL>def _check(fn):<EOL><INDENT>@wraps(fn)<EOL>def wrapper(*args, **kwargs):<EOL><INDENT>ret = fn(*args, **kwargs)<EOL>flags = reduce(<EOL>self._parser, [dict(num=mark, flags=[]), <NUM_LIT:2>, <NUM_LIT:1>])["<STR_LIT>"]<EOL>if <NUM_LIT:1> in flags:<EOL><INDENT>if self._has_error():<EOL><INDENT>raise AutoItError(err_msg)<EOL><DEDENT><DEDENT>if <NUM_LIT:2> in flags:<EOL><INDENT>if self._has_unexpected_ret(ret, unexpected_ret):<EOL><INDENT>raise AutoItError(err_msg)<EOL><DEDENT><DEDENT>return ret<EOL><DEDENT>return wrapper<EOL><DEDENT>return _check<EOL>

:param mark:
    0 - do not need check return value or error()
    1 - check error()
    2 - check return value


@api.check(<NUM_LIT:2>, "<STR_LIT>")<EOL>def win_activate(title, **kwargs):

text = kwargs.get("<STR_LIT:text>", "<STR_LIT>")<EOL>ret = AUTO_IT.AU3_WinActivate(LPCWSTR(title), LPCWSTR(text))<EOL>return ret<EOL>

Activates (gives focus to) a window.
:param title:
:param text:
:return:


ret = AUTO_IT.AU3_WinActivateByHandle(HWND(handle))<EOL>return ret<EOL>


text = kwargs.get("<STR_LIT:text>", "<STR_LIT>")<EOL>ret = AUTO_IT.AU3_WinActive(LPCWSTR(title), LPCWSTR(text))<EOL>return ret<EOL>


ret = AUTO_IT.AU3_WinActiveByHandle(HWND(handle))<EOL>return ret<EOL>


@api.check(<NUM_LIT:2>, "<STR_LIT>")<EOL>def win_close(title, **kwargs):

text = kwargs.get("<STR_LIT:text>", "<STR_LIT>")<EOL>ret = AUTO_IT.AU3_WinClose(LPCWSTR(title), LPCWSTR(text))<EOL>return ret<EOL>


ret = AUTO_IT.AU3_WinCloseByHandle(HWND(handle))<EOL>return ret<EOL>


text = kwargs.get("<STR_LIT:text>", "<STR_LIT>")<EOL>ret = AUTO_IT.AU3_WinExists(LPCWSTR(title), LPCWSTR(text))<EOL>return ret<EOL>

Checks to see if a specified window exists.
:param title: The title of the window to check.
:param text: The text of the window to check.
:return: Returns 1 if the window exists, otherwise returns 0.


ret = AUTO_IT.AU3_WinExistsByHandle(HWND(handle))<EOL>return ret<EOL>


p = POINT()<EOL>AUTO_IT.AU3_WinGetCaretPos(byref(p))<EOL>return p.x, p.y<EOL>

Returns the coordinates of the caret in the foreground window
:return:


def win_get_class_list(title, buf_size=<NUM_LIT:200>, **kwargs):

text = kwargs.get("<STR_LIT:text>", "<STR_LIT>")<EOL>rec_text = create_unicode_buffer(buf_size)  <EOL>AUTO_IT.AU3_WinGetClassList(LPCWSTR(title), LPCWSTR(text),<EOL>rec_text, INT(buf_size))<EOL>msg = rec_text.value.rstrip()<EOL>return msg<EOL>

:param title:
:param text:
:param buf_size:
:return:


rec_text = create_unicode_buffer(buf_size)<EOL>AUTO_IT.AU3_WinGetClassListByHandle(HWND(handle), rec_text, INT(buf_size))<EOL>msg = rec_text.value.rstrip()<EOL>return msg<EOL>

:param handle:
:param buf_size:
:return:


text = kwargs.get("<STR_LIT:text>", "<STR_LIT>")<EOL>rect = RECT()<EOL>ret = AUTO_IT.AU3_WinGetClientSize(LPCWSTR(title), LPCWSTR(text),<EOL>byref(rect))<EOL>if ret == <NUM_LIT:1>:<EOL><INDENT>raise AutoItError(<EOL>"<STR_LIT>")<EOL><DEDENT>return rect.right, rect.bottom<EOL>


rect = RECT()<EOL>ret = AUTO_IT.AU3_WinGetClientSizeByHandle(HWND(handle), byref(rect))<EOL>if ret == <NUM_LIT:1>:<EOL><INDENT>raise AutoItError("<STR_LIT>")<EOL><DEDENT>return rect.right, rect.bottom<EOL>


@api.check(<NUM_LIT:3>, "<STR_LIT>")<EOL>def win_get_handle(title, **kwargs):

text = kwargs.get("<STR_LIT:text>", "<STR_LIT>")<EOL>ret = AUTO_IT.AU3_WinGetHandle(LPCWSTR(title), LPCWSTR(text))<EOL>return ret<EOL>


@api.check(<NUM_LIT:1>, "<STR_LIT>")<EOL>def win_get_handle_as_text(title, buf_size=<NUM_LIT:16>, **kwargs):

text = kwargs.get("<STR_LIT:text>", "<STR_LIT>")<EOL>rec_text = create_unicode_buffer(buf_size)<EOL>AUTO_IT.AU3_WinGetHandleAsText(LPCWSTR(title), LPCWSTR(text),<EOL>rec_text, INT(buf_size))<EOL>msg = rec_text.value<EOL>return msg<EOL>


text = kwargs.get("<STR_LIT:text>", "<STR_LIT>")<EOL>rect = RECT()<EOL>res = AUTO_IT.AU3_WinGetPos(LPCWSTR(title), LPCWSTR(text), byref(rect))<EOL>if res == <NUM_LIT:1>:<EOL><INDENT>raise AutoItError("<STR_LIT>")<EOL><DEDENT>return rect.left, rect.top, rect.right, rect.bottom<EOL>


rect = RECT()<EOL>res = AUTO_IT.AU3_WinGetPosByHandle(HWND(handle), byref(rect))<EOL>if res == <NUM_LIT:1>:<EOL><INDENT>raise AutoItError("<STR_LIT>" % str(handle))<EOL><DEDENT>return rect.left, rect.top, rect.right, rect.bottom<EOL>


@api.check(<NUM_LIT:2>, "<STR_LIT>", unexpected_ret=(-<NUM_LIT:1>,))<EOL>def win_get_process(title, **kwargs):

text = kwargs.get("<STR_LIT:text>", "<STR_LIT>")<EOL>res = AUTO_IT.AU3_WinGetProcess(LPCWSTR(title), LPCWSTR(text))<EOL>return res<EOL>


@api.check(<NUM_LIT:2>, "<STR_LIT>", unexpected_ret=(-<NUM_LIT:1>,))<EOL>def win_get_process_by_handle(handle):

res = AUTO_IT.AU3_WinGetProcessByHandle(HWND(handle))<EOL>return res<EOL>


@api.check(<NUM_LIT:2>, "<STR_LIT>")<EOL>def win_get_state(title, **kwargs):

text = kwargs.get("<STR_LIT:text>", "<STR_LIT>")<EOL>res = AUTO_IT.AU3_WinGetState(LPCWSTR(title), LPCWSTR(text))<EOL>return res<EOL>

Retrieves the state of a given window.
:param title:
:param text:
:return:
1 = Window exists
2 = Window is visible
4 = Windows is enabled
8 = Window is active
16 = Window is minimized
32 = Windows is maximized


res = AUTO_IT.AU3_WinGetStateByHandle(HWND(handle))<EOL>return res<EOL>


def win_get_text(title, buf_size=<NUM_LIT>, **kwargs):

text = kwargs.get("<STR_LIT:text>", "<STR_LIT>")<EOL>ret_text = create_unicode_buffer(buf_size)<EOL>AUTO_IT.AU3_WinGetText(LPCWSTR(title), LPCWSTR(text), ret_text,<EOL>INT(buf_size))<EOL>val = ret_text.value.rstrip()<EOL>return val<EOL>


ret_text = create_unicode_buffer(buf_size)<EOL>AUTO_IT.AU3_WinGetTextByHandle(HWND(handle), ret_text, INT(buf_size))<EOL>return ret_text.value.rstrip()<EOL>


def win_get_title(title, buf_size=<NUM_LIT>, **kwargs):

text = kwargs.get("<STR_LIT:text>", "<STR_LIT>")<EOL>ret_text = create_unicode_buffer(buf_size)<EOL>AUTO_IT.AU3_WinGetTitle(LPCWSTR(title), LPCWSTR(text), ret_text,<EOL>INT(buf_size))<EOL>val = ret_text.value.rstrip()<EOL>return val<EOL>


ret_text = create_unicode_buffer(buf_size)<EOL>AUTO_IT.AU3_WinGetTitleByHandle(HWND(handle), ret_text, INT(buf_size))<EOL>val = ret_text.value.rstrip()<EOL>return val<EOL>


@api.check(<NUM_LIT:2>, "<STR_LIT>")<EOL>def win_kill(title, **kwargs):

text = kwargs.get("<STR_LIT:text>", "<STR_LIT>")<EOL>ret = AUTO_IT.AU3_WinKill(LPCWSTR(title), LPCWSTR(text))<EOL>return ret<EOL>


ret = AUTO_IT.AU3_WinKillByHandle(HWND(handle))<EOL>return ret<EOL>


@api.check(<NUM_LIT:2>, "<STR_LIT>")<EOL>def win_menu_select_item(title, *items, **kwargs):

text = kwargs.get("<STR_LIT:text>", "<STR_LIT>")<EOL>if not (<NUM_LIT:0> < len(items) < <NUM_LIT:8>):<EOL><INDENT>raise ValueError("<STR_LIT>")<EOL><DEDENT>f_items = [LPCWSTR(item) for item in items]<EOL>for i in xrange(<NUM_LIT:8> - len(f_items)):<EOL><INDENT>f_items.append(LPCWSTR("<STR_LIT>"))<EOL><DEDENT>ret = AUTO_IT.AU3_WinMenuSelectItem(LPCWSTR(title), LPCWSTR(text),<EOL>*f_items)<EOL>return ret<EOL>

Usage:
    win_menu_select_item("[CLASS:Notepad]", "", u"文件(&F)", u"退出(&X)")
:param title:
:param text:
:param items:
:return:


@api.check(<NUM_LIT:2>, "<STR_LIT>")<EOL>def win_menu_select_item_by_handle(handle, *items):

if not (<NUM_LIT:0> < len(items) < <NUM_LIT:8>):<EOL><INDENT>raise ValueError("<STR_LIT>")<EOL><DEDENT>f_items = [LPCWSTR(item) for item in items]<EOL>for i in xrange(<NUM_LIT:8> - len(f_items)):<EOL><INDENT>f_items.append(LPCWSTR("<STR_LIT>"))<EOL><DEDENT>ret = AUTO_IT.AU3_WinMenuSelectItemByHandle(HWND(handle), *f_items)<EOL>return ret<EOL>


@api.check(<NUM_LIT:2>, "<STR_LIT>")<EOL>def win_move(title, x, y, width=-<NUM_LIT:1>, height=-<NUM_LIT:1>, **kwargs):

text = kwargs.get("<STR_LIT:text>", "<STR_LIT>")<EOL>ret = AUTO_IT.AU3_WinMove(LPCWSTR(title), LPCWSTR(text), INT(x), INT(y),<EOL>INT(width), INT(height))<EOL>return ret<EOL>

:param title:
:param text:
:param x:
:param y:
:param width:
:param height:
:return:


@api.check(<NUM_LIT:2>, "<STR_LIT>")<EOL>def win_move_by_handle(handle, x, y, width=-<NUM_LIT:1>, height=-<NUM_LIT:1>):

ret = AUTO_IT.AU3_WinMoveByHandle(HWND(handle), INT(x), INT(y), INT(width),<EOL>INT(height))<EOL>return ret<EOL>

:param handle:
:param x:
:param y:
:param width:
:param height:
:return:


@api.check(<NUM_LIT:2>, "<STR_LIT>")<EOL>def win_set_on_top(title, flag=<NUM_LIT:1>, **kwargs):

text = kwargs.get("<STR_LIT:text>", "<STR_LIT>")<EOL>ret = AUTO_IT.AU3_WinSetOnTop(LPCWSTR(title), LPCWSTR(text), INT(flag))<EOL>return ret<EOL>

:param title:
:param flag: 1=set on top flag, 0 = remove on top flag
:param kwargs:
:return:


@api.check(<NUM_LIT:2>, "<STR_LIT>")<EOL>def win_set_on_top_by_handle(handle, flag=<NUM_LIT:1>):

ret = AUTO_IT.AU3_WinSetOnTopByHandle(HWND(handle), INT(flag))<EOL>return ret<EOL>


@api.check(<NUM_LIT:2>, "<STR_LIT>")<EOL>def win_set_state(title, flag=properties.SW_SHOW, **kwargs):

text = kwargs.get("<STR_LIT:text>", "<STR_LIT>")<EOL>ret = AUTO_IT.AU3_WinSetState(LPCWSTR(title), LPCWSTR(text), INT(flag))<EOL>return ret<EOL>

:param title:
:param flag: The "show" flag of the executed program:
    SW_HIDE = Hide window
    SW_SHOW = Shows a previously hidden window
    SW_MINIMIZE = Minimize window
    SW_MAXIMIZE = Maximize window
    SW_RESTORE = Undoes a window minimization or maximization
:param kwargs:
:return:


@api.check(<NUM_LIT:2>, "<STR_LIT>")<EOL>def win_set_state_by_handle(handle, flag=properties.SW_SHOW):

ret = AUTO_IT.AU3_WinSetStateByHandle(HWND(handle), INT(flag))<EOL>return ret<EOL>


@api.check(<NUM_LIT:2>, "<STR_LIT>")<EOL>def win_set_title(title, new_title, **kwargs):

text = kwargs.get("<STR_LIT:text>", "<STR_LIT>")<EOL>ret = AUTO_IT.AU3_WinSetTitle(LPCWSTR(title), LPCWSTR(text),<EOL>LPCWSTR(new_title))<EOL>return ret<EOL>

:param title:
:param new_title:
:param kwargs:
:return:


@api.check(<NUM_LIT:2>, "<STR_LIT>")<EOL>def win_set_title_by_handle(handle, new_title):

ret = AUTO_IT.AU3_WinSetTitleByHandle(HWND(handle), LPCWSTR(new_title))<EOL>return ret<EOL>

:param handle:
:param new_title:
:return:


@api.check(<NUM_LIT:2>, "<STR_LIT>")<EOL>def win_set_trans(title, trans, **kwargs):

text = kwargs.get("<STR_LIT:text>", "<STR_LIT>")<EOL>ret = AUTO_IT.AU3_WinSetTrans(LPCWSTR(title), LPCWSTR(text), INT(trans))<EOL>return ret<EOL>

Sets the transparency of a window.
:param title:
:param trans: A number in the range 0 - 255. The larger the number,
    the more transparent the window will become.
:param kwargs:
:return:


@api.check(<NUM_LIT:2>, "<STR_LIT>")<EOL>def win_set_trans_by_handle(handle, trans):

ret = AUTO_IT.AU3_WinSetTransByHandle(HWND(handle), INT(trans))<EOL>return ret<EOL>


@api.check(<NUM_LIT:2>, "<STR_LIT>")<EOL>def win_wait(title, timeout=<NUM_LIT:0>, **kwargs):

text = kwargs.get("<STR_LIT:text>", "<STR_LIT>")<EOL>ret = AUTO_IT.AU3_WinWait(LPCWSTR(title), LPCWSTR(text), INT(timeout))<EOL>return ret<EOL>

:param title:
:param timeout:
:param kwargs:
:return:


@api.check(<NUM_LIT:2>, "<STR_LIT>")<EOL>def win_wait_by_handle(handle, timeout):

ret = AUTO_IT.AU3_WinWaitByHandle(HWND(handle), INT(timeout))<EOL>return ret<EOL>


@api.check(<NUM_LIT:2>, "<STR_LIT>")<EOL>def win_wait_active(title, timeout=<NUM_LIT:0>, **kwargs):

text = kwargs.get("<STR_LIT:text>", "<STR_LIT>")<EOL>ret = AUTO_IT.AU3_WinWaitActive(LPCWSTR(title), LPCWSTR(text),<EOL>INT(timeout))<EOL>return ret<EOL>


@api.check(<NUM_LIT:2>, "<STR_LIT>")<EOL>def win_wait_active_by_handle(handle, timeout):

ret = AUTO_IT.AU3_WinWaitActiveByHandle(HWND(handle), INT(timeout))<EOL>return ret<EOL>


@api.check(<NUM_LIT:2>, "<STR_LIT>")<EOL>def win_wait_close(title, timeout=<NUM_LIT:0>, **kwargs):

text = kwargs.get("<STR_LIT:text>", "<STR_LIT>")<EOL>ret = AUTO_IT.AU3_WinWaitClose(LPCWSTR(title), LPCWSTR(text), INT(timeout))<EOL>return ret<EOL>


@api.check(<NUM_LIT:2>, "<STR_LIT>")<EOL>def win_wait_close_by_handle(handle, timeout):

ret = AUTO_IT.AU3_WinWaitCloseByHandle(HWND(handle), INT(timeout))<EOL>return ret<EOL>


@api.check(<NUM_LIT:2>, "<STR_LIT>")<EOL>def win_wait_not_active(title, timeout=<NUM_LIT:0>, **kwargs):

text = kwargs.get("<STR_LIT:text>", "<STR_LIT>")<EOL>ret = AUTO_IT.AU3_WinWaitNotActive(LPCWSTR(title), LPCWSTR(text),<EOL>INT(timeout))<EOL>return ret<EOL>


@api.check(<NUM_LIT:2>, "<STR_LIT>")<EOL>def win_wait_not_active_by_handle(handle, timeout):

ret = AUTO_IT.AU3_WinWaitNotActiveByHandle(HWND(handle), INT(timeout))<EOL>return ret<EOL>


@api.check(<NUM_LIT:1>, "<STR_LIT>")<EOL>def run(filename, work_dir="<STR_LIT>", show_flag=Properties.SW_SHOWNORMAL):

ret = AUTO_IT.AU3_Run(LPCWSTR(filename), LPCWSTR(work_dir),<EOL>INT(show_flag))<EOL>return ret<EOL>

:param filename:
:param work_dir:
:param show_flag:
:return:


@api.check(<NUM_LIT:1>, "<STR_LIT>")<EOL>def run_wait(filename, work_dir="<STR_LIT>", show_flag=Properties.SW_SHOWNORMAL):

ret = AUTO_IT.AU3_RunWait(LPCWSTR(filename), LPCWSTR(work_dir),<EOL>INT(show_flag))<EOL>return ret<EOL>


ret = AUTO_IT.AU3_ProcessClose(LPCWSTR(process))<EOL>return ret<EOL>


ret = AUTO_IT.AU3_ProcessExists(LPCWSTR(process))<EOL>return ret<EOL>


ret = AUTO_IT.AU3_ProcessSetPriority(LPCWSTR(process), INT(priority))<EOL>if ret == <NUM_LIT:0>:<EOL><INDENT>if error() == <NUM_LIT:1>:<EOL><INDENT>raise AutoItError("<STR_LIT>")<EOL><DEDENT>elif error() == <NUM_LIT:2>:<EOL><INDENT>raise AutoItError("<STR_LIT>")<EOL><DEDENT><DEDENT>return ret<EOL>

Changes the priority of a process
:param process: The name or PID of the process to check.
:param priority:A flag which determines what priority to set
    0 - Idle/Low
    1 - Below Normal (Not supported on Windows 95/98/ME)
    2 - Normal
    3 - Above Normal (Not supported on Windows 95/98/ME)
    4 - High
    5 - Realtime (Use with caution, may make the system unstable)
:return:


@api.check(<NUM_LIT:2>, "<STR_LIT>")<EOL>def process_wait(process, timeout=<NUM_LIT:0>):

ret = AUTO_IT.AU3_ProcessWait(LPCWSTR(process), INT(timeout))<EOL>return ret<EOL>

Pauses script execution until a given process exists.
:param process:
:param timeout:
:return:


@api.check(<NUM_LIT:2>, "<STR_LIT>")<EOL>def process_wait_close(process, timeout=<NUM_LIT:0>):

ret = AUTO_IT.AU3_ProcessWaitClose(LPCWSTR(process), INT(timeout))<EOL>return ret<EOL>

Pauses script execution until a given process does not exist.
:param process:
:param timeout:
:return:


@api.check(<NUM_LIT:1>, "<STR_LIT>")<EOL>def run_as(user, domain, password, filename, logon_flag=<NUM_LIT:1>, work_dir="<STR_LIT>",<EOL>show_flag=Properties.SW_SHOWNORMAL):

ret = AUTO_IT.AU3_RunAs(<EOL>LPCWSTR(user), LPCWSTR(domain), LPCWSTR(password), INT(logon_flag),<EOL>LPCWSTR(filename), LPCWSTR(work_dir), INT(show_flag)<EOL>)<EOL>return ret<EOL>

Runs an external program.
:param user: username The user name to use.
:param domain: The domain name to use.
:param password: The password to use.
:param logon_flag: 0 = do not load the user profile, 1 = (default) load
    the user profile, 2 = use for net credentials only
:param filename: The name of the executable (EXE, BAT, COM, or PIF) to run.
:param work_dir: The working directory.
:param show_flag: The "show" flag of the executed program:
    SW_HIDE = Hidden window
    SW_MINIMIZE = Minimized window
    SW_MAXIMIZE = Maximized window
:return:


@api.check(<NUM_LIT:1>, "<STR_LIT>")<EOL>def run_as_wait(user, domain, password, filename, logon_flag=<NUM_LIT:1>, work_dir="<STR_LIT>",<EOL>show_flag=Properties.SW_SHOWNORMAL):

ret = AUTO_IT.AU3_RunAsWait(<EOL>LPCWSTR(user), LPCWSTR(domain), LPCWSTR(password), INT(logon_flag),<EOL>LPCWSTR(filename), LPCWSTR(work_dir), INT(show_flag)<EOL>)<EOL>return ret<EOL>


ret = AUTO_IT.AU3_Shutdown(INT(code))<EOL>return ret<EOL>

:param code: The shutdown code is a combination of the following values:
    0 = Logoff
    1 = Shutdown
    2 = Reboot
    4 = Force
    8 = Power down
:return:


try:<EOL><INDENT>indent = min(len(line) - len(line.lstrip())<EOL>for line in lines if line)<EOL><DEDENT>except ValueError:<EOL><INDENT>return lines<EOL><DEDENT>else:<EOL><INDENT>return [line[indent:] for line in lines]<EOL><DEDENT>

Remove common indentation from string.

Unlike doctrim there is no special treatment of the first line.


return ['<STR_LIT>' + language] + unindent(lines) + ['<STR_LIT>']<EOL>

Mark the code segment for syntax highlighting.


sections = []<EOL>for line in lines:<EOL><INDENT>if is_heading(line):<EOL><INDENT>sections.append(get_heading(line))<EOL><DEDENT><DEDENT>return sections<EOL>

Find all section names and return a list with their names.


if not sections:<EOL><INDENT>return []<EOL><DEDENT>outer = min(n for n,t in sections)<EOL>refs = []<EOL>for ind,sec in sections:<EOL><INDENT>if maxdepth and ind-outer+<NUM_LIT:1> > maxdepth:<EOL><INDENT>continue<EOL><DEDENT>ref = sec.lower()<EOL>ref = ref.replace('<STR_LIT>', '<STR_LIT>')<EOL>ref = ref.replace('<STR_LIT:U+0020>', '<STR_LIT:->')<EOL>ref = ref.replace('<STR_LIT:?>', '<STR_LIT>')<EOL>refs.append("<STR_LIT:U+0020>"*(ind-outer) + "<STR_LIT>" % (sec, ref))<EOL><DEDENT>return refs<EOL>

Generate table of contents for array of section names.


def doc2md(docstr, title, min_level=<NUM_LIT:1>, more_info=False, toc=True, maxdepth=<NUM_LIT:0>):

text = doctrim(docstr)<EOL>lines = text.split('<STR_LIT:\n>')<EOL>sections = find_sections(lines)<EOL>if sections:<EOL><INDENT>level = min(n for n,t in sections) - <NUM_LIT:1><EOL><DEDENT>else:<EOL><INDENT>level = <NUM_LIT:1><EOL><DEDENT>shiftlevel = <NUM_LIT:0><EOL>if level < min_level:<EOL><INDENT>shiftlevel = min_level - level<EOL>level = min_level<EOL>sections = [(lev+shiftlevel, tit) for lev,tit in sections]<EOL><DEDENT>head = next((i for i, l in enumerate(lines) if is_heading(l)), <NUM_LIT:0>)<EOL>md = [<EOL>make_heading(level, title),<EOL>"<STR_LIT>",<EOL>] + lines[:head]<EOL>if toc:<EOL><INDENT>md += make_toc(sections, maxdepth)<EOL>md += ['<STR_LIT>']<EOL><DEDENT>md += _doc2md(lines[head:], shiftlevel)<EOL>if more_info:<EOL><INDENT>return (md, sections)<EOL><DEDENT>else:<EOL><INDENT>return "<STR_LIT:\n>".join(md)<EOL><DEDENT>


def mod2md(module, title, title_api_section, toc=True, maxdepth=<NUM_LIT:0>):

docstr = module.__doc__<EOL>text = doctrim(docstr)<EOL>lines = text.split('<STR_LIT:\n>')<EOL>sections = find_sections(lines)<EOL>if sections:<EOL><INDENT>level = min(n for n,t in sections) - <NUM_LIT:1><EOL><DEDENT>else:<EOL><INDENT>level = <NUM_LIT:1><EOL><DEDENT>api_md = []<EOL>api_sec = []<EOL>if title_api_section and module.__all__:<EOL><INDENT>sections.append((level+<NUM_LIT:1>, title_api_section))<EOL>for name in module.__all__:<EOL><INDENT>api_sec.append((level+<NUM_LIT:2>, "<STR_LIT>" + name + "<STR_LIT>"))<EOL>api_md += ['<STR_LIT>', '<STR_LIT>']<EOL>entry = module.__dict__[name]<EOL>if entry.__doc__:<EOL><INDENT>md, sec = doc2md(entry.__doc__, "<STR_LIT>" + name + "<STR_LIT>",<EOL>min_level=level+<NUM_LIT:2>, more_info=True, toc=False)<EOL>api_sec += sec<EOL>api_md += md<EOL><DEDENT><DEDENT><DEDENT>sections += api_sec<EOL>head = next((i for i, l in enumerate(lines) if is_heading(l)), <NUM_LIT:0>)<EOL>md = [<EOL>make_heading(level, title),<EOL>"<STR_LIT>",<EOL>] + lines[:head]<EOL>if toc:<EOL><INDENT>md += make_toc(sections, maxdepth)<EOL>md += ['<STR_LIT>']<EOL><DEDENT>md += _doc2md(lines[head:])<EOL>md += [<EOL>'<STR_LIT>',<EOL>'<STR_LIT>',<EOL>make_heading(level+<NUM_LIT:1>, title_api_section),<EOL>]<EOL>if toc:<EOL><INDENT>md += ['<STR_LIT>']<EOL>md += make_toc(api_sec, <NUM_LIT:1>)<EOL><DEDENT>md += api_md<EOL>return "<STR_LIT:\n>".join(md)<EOL>

Generate markdown document from module, including API section.


import argparse<EOL>parser = argparse.ArgumentParser()<EOL>parser.add_argument('<STR_LIT>', dest="<STR_LIT>",<EOL>action="<STR_LIT:store_true>", default=False)<EOL>args, sys.argv = parser.parse_known_args(sys.argv)<EOL>if args.doc:<EOL><INDENT>import doc2md, pypandoc<EOL>md = doc2md.doc2md(doc2md.__doc__, "<STR_LIT>", toc=False)<EOL>long_description = pypandoc.convert(md, '<STR_LIT>', format='<STR_LIT>')<EOL><DEDENT>else:<EOL><INDENT>return None<EOL><DEDENT>


@yaz.task<EOL><INDENT>def breakfast(self, message="<STR_LIT>", shout: bool = False):<DEDENT>

return self.helper.output(message, shout)<EOL>


@yaz.task<EOL><INDENT>def lunch(self, message="<STR_LIT>", shout: bool = False):<DEDENT>


@yaz.task<EOL><INDENT>def dinner(self, message="<STR_LIT>", shout: bool = False):<DEDENT>


@yaz.task<EOL>def say(message: str = "<STR_LIT>"):

return message<EOL>


assert callable(decorator_func), type(decorator_func)<EOL>def _decorator(func=None, **kwargs):<EOL><INDENT>assert func is None or callable(func), type(func)<EOL>if func:<EOL><INDENT>return decorator_func(func, **kwargs)<EOL><DEDENT>else:<EOL><INDENT>def _decorator_helper(func):<EOL><INDENT>return decorator_func(func, **kwargs)<EOL><DEDENT>return _decorator_helper<EOL><DEDENT><DEDENT>return _decorator<EOL>

Allows a decorator to be called with or without keyword arguments.


assert white_list is None or isinstance(white_list, list), type(white_list)<EOL>if white_list is not None:<EOL><INDENT>white_list = set(item if isinstance(item, str) else item.__qualname__ for item in white_list)<EOL><DEDENT>tree = dict((task.qualified_name, task)<EOL>for task<EOL>in _task_list.values()<EOL>if white_list is None or task.qualified_name in white_list)<EOL>plugins = get_plugin_list()<EOL>for plugin in [plugin for plugin in plugins.values() if white_list is None or plugin.__qualname__ in white_list]:<EOL><INDENT>tasks = [func<EOL>for _, func<EOL>in inspect.getmembers(plugin)<EOL>if inspect.isfunction(func) and hasattr(func, "<STR_LIT>")]<EOL>if len(tasks) == <NUM_LIT:0>:<EOL><INDENT>continue<EOL><DEDENT>node = tree<EOL>for name in plugin.__qualname__.split("<STR_LIT:.>"):<EOL><INDENT>if not name in node:<EOL><INDENT>node[name] = {}<EOL><DEDENT>node = node[name]<EOL><DEDENT>for func in tasks:<EOL><INDENT>logger.debug("<STR_LIT>", func)<EOL>node[func.__name__] = Task(plugin_class=plugin, func=func, config=func.yaz_task_config)<EOL><DEDENT><DEDENT>return tree<EOL>

Returns a tree of Task instances

    The tree is comprised of dictionaries containing strings for
    keys and either dictionaries or Task instances for values.

    When WHITE_LIST is given, only the tasks and plugins in this
    list will become part of the task tree.  The WHITE_LIST may
    contain either strings, corresponding to the task of plugin
    __qualname__, or, preferable, the WHITE_LIST contains
    links to the task function or plugin class instead.


if func.__name__ == func.__qualname__:<EOL><INDENT>assert not func.__qualname__ in _task_list, "<STR_LIT>".format(func.__qualname__)<EOL>logger.debug("<STR_LIT>", func)<EOL>_task_list[func.__qualname__] = Task(plugin_class=None, func=func, config=config)<EOL><DEDENT>else:<EOL><INDENT>func.yaz_task_config = config<EOL><DEDENT>return func<EOL>

Declare a function or method to be a Yaz task

    @yaz.task
    def talk(message: str = "Hello World!"):
        return message

    Or... group multiple tasks together

    class Tools(yaz.Plugin):
        @yaz.task
        def say(self, message: str = "Hello World!"):
            return message

        @yaz.task(option__choices=["A", "B", "C"])
        def choose(self, option: str = "A"):
            return option


return self.Documentation(inspect.getdoc(self.plugin_class))<EOL>

Returns documentation for the plugin class


return self.Documentation(inspect.getdoc(self.func))<EOL>

Returns documentation for the task function


return self.func.__qualname__<EOL>


start = datetime.datetime.now()<EOL>logger.info("<STR_LIT>", self)<EOL>try:<EOL><INDENT>if self.plugin_class:<EOL><INDENT>result = self.func(get_plugin_instance(self.plugin_class), **kwargs)<EOL><DEDENT>else:<EOL><INDENT>result = self.func(**kwargs)<EOL><DEDENT>if inspect.iscoroutinefunction(self.func):<EOL><INDENT>assert inspect.iscoroutine(<EOL>result), "<STR_LIT>"<EOL>loop = asyncio.get_event_loop()<EOL>if loop.is_closed():<EOL><INDENT>loop = asyncio.new_event_loop()<EOL>asyncio.set_event_loop(loop)<EOL><DEDENT>result = loop.run_until_complete(result)<EOL>loop.close()<EOL><DEDENT><DEDENT>finally:<EOL><INDENT>stop = datetime.datetime.now()<EOL>logger.info("<STR_LIT>", self, stop - start)<EOL><DEDENT>return result<EOL>


if self.plugin_class is None:<EOL><INDENT>sig = inspect.signature(self.func)<EOL>for index, parameter in enumerate(sig.parameters.values()):<EOL><INDENT>if not parameter.kind in [parameter.POSITIONAL_ONLY, parameter.KEYWORD_ONLY, parameter.POSITIONAL_OR_KEYWORD]:<EOL><INDENT>raise RuntimeError("<STR_LIT>".format(parameter, parameter.kind))<EOL><DEDENT>yield parameter<EOL><DEDENT><DEDENT>else:<EOL><INDENT>var_keyword_seen = set()<EOL>for cls in inspect.getmro(self.plugin_class):<EOL><INDENT>if issubclass(cls, BasePlugin) and hasattr(cls, self.func.__name__):<EOL><INDENT>func = getattr(cls, self.func.__name__)<EOL>logger.debug("<STR_LIT>", func, cls)<EOL>var_keyword_found = False<EOL>sig = inspect.signature(func)<EOL>for index, parameter in enumerate(sig.parameters.values()):<EOL><INDENT>if index == <NUM_LIT:0>:<EOL><INDENT>continue<EOL><DEDENT>if parameter.kind == inspect.Parameter.VAR_KEYWORD:<EOL><INDENT>var_keyword_found = True<EOL>continue<EOL><DEDENT>if parameter.kind in [parameter.POSITIONAL_ONLY, parameter.VAR_POSITIONAL]:<EOL><INDENT>raise RuntimeError("<STR_LIT>".format(func, parameter))<EOL><DEDENT>if not parameter.name in var_keyword_seen:<EOL><INDENT>var_keyword_seen.add(parameter.name)<EOL>logger.debug("<STR_LIT>", parameter, parameter.kind)<EOL>yield parameter<EOL><DEDENT><DEDENT>if not var_keyword_found:<EOL><INDENT>break<EOL><DEDENT><DEDENT><DEDENT><DEDENT>


def get_configuration(self, key, default=None):

if key in self.config:<EOL><INDENT>return self.config.get(key)<EOL><DEDENT>else:<EOL><INDENT>return default<EOL><DEDENT>


@yaz.task<EOL><INDENT>def main(self, pos1: str, pos2: str, pos3: str, pos_or_key1: str = "<STR_LIT>", pos_or_key2: str = "<STR_LIT>", pos_or_key3: str = "<STR_LIT>", *, key1: str = "<STR_LIT>", key2: str = "<STR_LIT>", key3: str = "<STR_LIT>"):<DEDENT>

return [pos1, pos2, pos3, pos_or_key1, pos_or_key2, pos_or_key3, key1, key2, key3]<EOL>


@yaz.task<EOL><INDENT>def main(self, pos1: str, pos2: str, pos_or_key1: str = "<STR_LIT>", pos_or_key2: str = "<STR_LIT>", *, key1: str = "<STR_LIT>", key2: str = "<STR_LIT>", extra2: str = "<STR_LIT>", **kwargs):<DEDENT>

return super().main(pos1, pos2, pos_or_key1=pos_or_key1, pos_or_key2=pos_or_key2, key1=key1, key2=key2, **kwargs) + [extra2]<EOL>


@yaz.task<EOL><INDENT>def main(self, pos1: str, pos_or_key1: str = "<STR_LIT>", *, key1: str = "<STR_LIT>", extra1: str = "<STR_LIT>", **kwargs):<DEDENT>

return super().main(pos1, pos_or_key1=pos_or_key1, key1=key1, **kwargs) + [extra1]<EOL>


return "<STR_LIT>"<EOL>


@yaz.task(choice__choices=["<STR_LIT:yes>", "<STR_LIT>", "<STR_LIT>"])<EOL><INDENT>def required_choice(self, choice):<DEDENT>

return self.choices[choice]<EOL>

This is the documentation for the required_choice task


pass<EOL>

This is the documentation for the one_line_doc_string task


pass<EOL>

This is the documentation for the multi_line_doc_string task

This is the long description, for example:
bla bla,
etc...


pass<EOL>

This is the documentation for the parameter_help task


def main(argv=None, white_list=None, load_yaz_extension=True):

assert argv is None or isinstance(argv, list), type(argv)<EOL>assert white_list is None or isinstance(white_list, list), type(white_list)<EOL>assert isinstance(load_yaz_extension, bool), type(load_yaz_extension)<EOL>argv = sys.argv if argv is None else argv<EOL>assert len(argv) > <NUM_LIT:0>, len(argv)<EOL>if load_yaz_extension:<EOL><INDENT>load("<STR_LIT>", "<STR_LIT>")<EOL><DEDENT>parser = Parser(prog=argv[<NUM_LIT:0>])<EOL>parser.add_task_tree(get_task_tree(white_list))<EOL>task, kwargs = parser.parse_arguments(argv)<EOL>if task:<EOL><INDENT>try:<EOL><INDENT>result = task(**kwargs)<EOL>if isinstance(result, bool):<EOL><INDENT>code = <NUM_LIT:0> if result else <NUM_LIT:1><EOL>output = None<EOL><DEDENT>elif isinstance(result, int):<EOL><INDENT>code = result % <NUM_LIT><EOL>output = None<EOL><DEDENT>else:<EOL><INDENT>code = <NUM_LIT:0><EOL>output = result<EOL><DEDENT><DEDENT>except Error as error:<EOL><INDENT>code = error.return_code<EOL>output = error<EOL><DEDENT><DEDENT>else:<EOL><INDENT>code = <NUM_LIT:1><EOL>output = parser.format_help().rstrip()<EOL><DEDENT>if output is not None:<EOL><INDENT>print(output)<EOL><DEDENT>sys.exit(code)<EOL>

The entry point for a yaz script

    This will almost always be called from a python script in
    the following manner:

        if __name__ == "__main__":
            yaz.main()

    This function will perform the following steps:

    1. It will load any additional python code from
       the yaz_extension python module located in the
       ~/.yaz directory when LOAD_YAZ_EXTENSION is True
       and the yaz_extension module exists

    2. It collects all yaz tasks and plugins.  When WHITE_LIST
       is a non-empty list, only the tasks and plugins located
       therein will be considered

    3. It will parse arguments from ARGV, or the command line
       when ARGV is not given, resulting in a yaz task or a parser
       help message.

    4. When a suitable task is found, this task is executed.  In
       case of a task which is part of a plugin, i.e. class, then
       this plugin is initialized, possibly resulting in other
       plugins to also be initialized if there are marked as
       `@yaz.dependency`.


directory_name = os.path.expanduser(directory_name)<EOL>if os.path.isdir(directory_name) and directory_name not in sys.path:<EOL><INDENT>sys.path.append(directory_name)<EOL><DEDENT>try:<EOL><INDENT>return importlib.import_module(module_name)<EOL><DEDENT>except ImportError:<EOL><INDENT>pass<EOL><DEDENT>

Try to load and return a module

    Will add DIRECTORY_NAME to sys.path and tries to import MODULE_NAME.

    For example:
    load("~/.yaz", "yaz_extension")


func.yaz_dependency_config = config<EOL>return func<EOL>

Declare a setter method to be called just after initializing a yaz.Plugin

    This decorator allows one or more plugin dependencies
    to be injected.  For example:

        class Helper(yaz.Plugin):
            pass

        class HelloWorld(yaz.Plugin):
            def __init__(self):
                self.helper = None

            @yaz.dependency
            def set_helper(self, helper: Helper):
                self.helper = helper

    In the above example, when the HelloWorld plugin is initialized,
    the set_helper method will be called immediately after the constructor
    finishes.

    Multiple dependencies may be injected in a single @yaz.dependency method.


global _yaz_plugin_classes<EOL>def get_recursively(cls, plugin_list):<EOL><INDENT>for plugin in cls.__subclasses__():<EOL><INDENT>if not (plugin.yaz_is_final() or plugin.__qualname__ in _yaz_plugin_classes):<EOL><INDENT>plugin_list[plugin.__qualname__].append(plugin)<EOL><DEDENT>get_recursively(plugin, plugin_list)<EOL><DEDENT>return plugin_list<EOL><DEDENT>def include_class(candidate, classes):<EOL><INDENT>for cls in classes:<EOL><INDENT>if candidate is cls:<EOL><INDENT>continue<EOL><DEDENT>if issubclass(cls, candidate):<EOL><INDENT>return False<EOL><DEDENT><DEDENT>return True<EOL><DEDENT>def get_plugin_type(qualname, plugins):<EOL><INDENT>classes = sorted(plugins, key=lambda plugin: plugin.yaz_get_ordinal())<EOL>classes = [cls for cls in classes if include_class(cls, classes)]<EOL>logger.debug("<STR_LIT>", qualname, [cls for cls in classes])<EOL>return type(qualname, tuple(classes) + (Final,), {})<EOL><DEDENT>logger.debug("<STR_LIT>" % _yaz_plugin_classes)<EOL>plugin_list = get_recursively(BasePlugin, collections.defaultdict(list))<EOL>_yaz_plugin_classes.update((qualname, get_plugin_type(qualname, plugins))<EOL>for qualname, plugins<EOL>in plugin_list.items())<EOL>assert isinstance(_yaz_plugin_classes, dict), type(_yaz_plugin_classes)<EOL>assert all(isinstance(qualname, str) for qualname in _yaz_plugin_classes.keys()), "<STR_LIT>"<EOL>assert all(issubclass(plugin_class, Final) for plugin_class in _yaz_plugin_classes.values()), "<STR_LIT>"<EOL>return _yaz_plugin_classes<EOL>

Finds all yaz plugins and returns them in a __qualname__: plugin_class dictionary


def get_plugin_instance(plugin_class, *args, **kwargs):

assert issubclass(plugin_class, BasePlugin), type(plugin_class)<EOL>global _yaz_plugin_instance_cache<EOL>qualname = plugin_class.__qualname__<EOL>if not qualname in _yaz_plugin_instance_cache:<EOL><INDENT>plugin_class = get_plugin_list()[qualname]<EOL>_yaz_plugin_instance_cache[qualname] = plugin = plugin_class(*args, **kwargs)<EOL>funcs = [func<EOL>for _, func<EOL>in inspect.getmembers(plugin)<EOL>if inspect.ismethod(func) and hasattr(func, "<STR_LIT>")]<EOL>for func in funcs:<EOL><INDENT>signature = inspect.signature(func)<EOL>assert all(parameter.kind is parameter.POSITIONAL_OR_KEYWORD and issubclass(parameter.annotation, BasePlugin) for parameter in signature.parameters.values()), "<STR_LIT>".format(func)<EOL>func(*[get_plugin_instance(parameter.annotation)<EOL>for parameter<EOL>in signature.parameters.values()])<EOL><DEDENT><DEDENT>return _yaz_plugin_instance_cache[qualname]<EOL>

Returns an instance of a fully initialized plugin class

    Every plugin class is kept in a plugin cache, effectively making
    every plugin into a singleton object.

    When a plugin has a yaz.dependency decorator, it will be called
    as well, before the instance is returned.


with open(os.path.join(cwd, "<STR_LIT>", "<STR_LIT:%s>" % doc_name), "<STR_LIT:r>") as f:<EOL><INDENT>return f.read()<EOL><DEDENT>


self.item_doc = self.get_doc("<STR_LIT>")<EOL>self.items_doc = self.get_doc("<STR_LIT>")<EOL>self.item_versions = self.get_doc("<STR_LIT>")<EOL>self.collection_versions = self.get_doc("<STR_LIT>")<EOL>self.collections_doc = self.get_doc("<STR_LIT>")<EOL>self.collection_doc = self.get_doc("<STR_LIT>")<EOL>self.collection_tags = self.get_doc("<STR_LIT>")<EOL>self.citation_doc = self.get_doc("<STR_LIT>")<EOL>self.attachments_doc = self.get_doc("<STR_LIT>")<EOL>self.tags_doc = self.get_doc("<STR_LIT>")<EOL>self.groups_doc = self.get_doc("<STR_LIT>")<EOL>self.item_templt = self.get_doc("<STR_LIT>")<EOL>self.item_types = self.get_doc("<STR_LIT>")<EOL>self.item_fields = self.get_doc("<STR_LIT>")<EOL>self.keys_response = self.get_doc("<STR_LIT>")<EOL>self.creation_doc = self.get_doc("<STR_LIT>")<EOL>self.item_file = self.get_doc("<STR_LIT>")<EOL>HTTPretty.enable()<EOL>HTTPretty.register_uri(<EOL>HTTPretty.GET,<EOL>"<STR_LIT>",<EOL>content_type="<STR_LIT:application/json>",<EOL>body=self.items_doc,<EOL>)<EOL>


HTTPretty.disable()<EOL>


def ib64_patched(self, attrsD, contentparams):

if attrsD.get("<STR_LIT>", "<STR_LIT>") == "<STR_LIT>":<EOL><INDENT>return <NUM_LIT:0><EOL><DEDENT>if self.contentparams["<STR_LIT:type>"].startswith("<STR_LIT>"):<EOL><INDENT>return <NUM_LIT:0><EOL><DEDENT>if self.contentparams["<STR_LIT:type>"].endswith("<STR_LIT>"):<EOL><INDENT>return <NUM_LIT:0><EOL><DEDENT>if self.contentparams["<STR_LIT:type>"].endswith("<STR_LIT>"):<EOL><INDENT>return <NUM_LIT:0><EOL><DEDENT>if self.contentparams["<STR_LIT:type>"].endswith("<STR_LIT>"):<EOL><INDENT>return <NUM_LIT:0><EOL><DEDENT>return <NUM_LIT:0><EOL>

Patch isBase64 to prevent Base64 encoding of JSON content


return str(uuid.uuid4().hex)<EOL>


def enc(self, *args, **kwargs):<EOL><INDENT>"""<STR_LIT>"""<EOL>return (func(self, item, **kwargs) for item in args)<EOL><DEDENT>return enc<EOL>


for i in range(<NUM_LIT:0>, len(l), n):<EOL><INDENT>yield l[i: i + n]<EOL><DEDENT>


def wrapped_f(self, *args, **kwargs):<EOL><INDENT>"""<STR_LIT>"""<EOL>if kwargs:<EOL><INDENT>self.add_parameters(**kwargs)<EOL><DEDENT>retrieved = self._retrieve_data(func(self, *args))<EOL>self.links = self._extract_links()<EOL>content = (<EOL>self.content.search(self.request.url)<EOL>and self.content.search(self.request.url).group(<NUM_LIT:0>)<EOL>or "<STR_LIT>"<EOL>)<EOL>formats = {<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT:application/json>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>}<EOL>content_type_header = self.request.headers["<STR_LIT:Content-Type>"].lower() + "<STR_LIT:;>"<EOL>re.compile("<STR_LIT>")<EOL>fmt = formats.get(<EOL>content_type_header[<NUM_LIT:0>: content_type_header.index("<STR_LIT:;>")],<EOL>"<STR_LIT>",<EOL>)<EOL>self.url_params = None<EOL>if "<STR_LIT>" in self.request.url:<EOL><INDENT>self.tag_data = False<EOL>return self._tags_data(retrieved.json())<EOL><DEDENT>if fmt == "<STR_LIT>":<EOL><INDENT>parsed = feedparser.parse(retrieved.text)<EOL>processor = self.processors.get(content)<EOL>return processor(parsed)<EOL><DEDENT>if fmt == "<STR_LIT>":<EOL><INDENT>self.snapshot = True<EOL><DEDENT>if fmt == "<STR_LIT>":<EOL><INDENT>parser = bibtexparser.bparser.BibTexParser(common_strings=True)<EOL>return parser.parse(retrieved.text)<EOL><DEDENT>elif fmt != "<STR_LIT>":<EOL><INDENT>return retrieved.content<EOL><DEDENT>else:<EOL><INDENT>return retrieved.json()<EOL><DEDENT><DEDENT>return wrapped_f<EOL>

Decorator for Zotero read API methods; calls _retrieve_data() and passes
the result to the correct processor, based on a lookup


def wrapper(self, *args, **kwargs):<EOL><INDENT>if not self.savedsearch:<EOL><INDENT>self.savedsearch = SavedSearch(self)<EOL><DEDENT>return func(self, *args, **kwargs)<EOL><DEDENT>return wrapper<EOL>


error_codes = {<EOL><NUM_LIT>: ze.UnsupportedParams,<EOL><NUM_LIT>: ze.UserNotAuthorised,<EOL><NUM_LIT>: ze.UserNotAuthorised,<EOL><NUM_LIT>: ze.ResourceNotFound,<EOL><NUM_LIT>: ze.Conflict,<EOL><NUM_LIT>: ze.PreConditionFailed,<EOL><NUM_LIT>: ze.RequestEntityTooLarge,<EOL><NUM_LIT>: ze.PreConditionRequired,<EOL><NUM_LIT>: ze.TooManyRequests,<EOL>}<EOL>def err_msg(req):<EOL><INDENT>"""<STR_LIT>"""<EOL>return "<STR_LIT>" % (<EOL>req.status_code,<EOL>req.url,<EOL>req.request.method,<EOL>req.text,<EOL>)<EOL><DEDENT>if error_codes.get(req.status_code):<EOL><INDENT>if req.status_code == <NUM_LIT>:<EOL><INDENT>delay = backoff.delay<EOL>if delay > <NUM_LIT:32>:<EOL><INDENT>backoff.reset()<EOL>raise ze.TooManyRetries(<EOL>"<STR_LIT>"<EOL>)<EOL><DEDENT>time.sleep(delay)<EOL>sess = requests.Session()<EOL>new_req = sess.send(req.request)<EOL>try:<EOL><INDENT>new_req.raise_for_status()<EOL><DEDENT>except requests.exceptions.HTTPError:<EOL><INDENT>error_handler(new_req)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>raise error_codes.get(req.status_code)(err_msg(req))<EOL><DEDENT><DEDENT>else:<EOL><INDENT>raise ze.HTTPError(err_msg(req))<EOL><DEDENT>


self.endpoint = "<STR_LIT>"<EOL>if library_id and library_type:<EOL><INDENT>self.library_id = library_id<EOL>self.library_type = library_type + "<STR_LIT:s>"<EOL><DEDENT>else:<EOL><INDENT>raise ze.MissingCredentials(<EOL>"<STR_LIT>"<EOL>)<EOL><DEDENT>self.api_key = api_key<EOL>self.preserve_json_order = preserve_json_order<EOL>self.url_params = None<EOL>self.tag_data = False<EOL>self.request = None<EOL>self.snapshot = False<EOL>self.temp_keys = set(["<STR_LIT:key>", "<STR_LIT>", "<STR_LIT>", "<STR_LIT>"])<EOL>self.fmt = re.compile(r"<STR_LIT>")<EOL>self.content = re.compile(r"<STR_LIT>")<EOL>self.processors = {<EOL>"<STR_LIT>": self._bib_processor,<EOL>"<STR_LIT>": self._citation_processor,<EOL>"<STR_LIT>": self._bib_processor,<EOL>"<STR_LIT>": self._bib_processor,<EOL>"<STR_LIT>": self._bib_processor,<EOL>"<STR_LIT>": self._csljson_processor,<EOL>"<STR_LIT>": self._bib_processor,<EOL>"<STR_LIT>": self._bib_processor,<EOL>"<STR_LIT>": self._bib_processor,<EOL>"<STR_LIT>": self._bib_processor,<EOL>"<STR_LIT>": self._bib_processor,<EOL>"<STR_LIT>": self._bib_processor,<EOL>"<STR_LIT>": self._bib_processor,<EOL>"<STR_LIT>": self._bib_processor,<EOL>"<STR_LIT>": self._json_processor,<EOL>"<STR_LIT:html>": self._bib_processor,<EOL>}<EOL>self.links = None<EOL>self.self_link = {}<EOL>self.templates = {}<EOL>self.savedsearch = None<EOL>


_headers = {<EOL>"<STR_LIT>": "<STR_LIT>" % __version__,<EOL>"<STR_LIT>": "<STR_LIT:%s>" % __api_version__,<EOL>}<EOL>if self.api_key:<EOL><INDENT>_headers["<STR_LIT>"] = "<STR_LIT>" % self.api_key<EOL><DEDENT>return _headers<EOL>


<EOL>thetime = datetime.datetime.utcnow().replace(tzinfo=pytz.timezone("<STR_LIT>"))<EOL>self.templates[key] = {"<STR_LIT>": response.json(), "<STR_LIT>": thetime}<EOL>return copy.deepcopy(response.json())<EOL>

Add a retrieved template to the cache for 304 checking
accepts a dict and key name, adds the retrieval time, and adds both
to self.templates as a new dict using the specified key


@cleanwrap<EOL><INDENT>def _cleanup(self, to_clean, allow=()):<DEDENT>

<EOL>if to_clean.keys() == ["<STR_LIT>", "<STR_LIT>", "<STR_LIT:version>", "<STR_LIT>", "<STR_LIT:key>", "<STR_LIT:data>"]:<EOL><INDENT>to_clean = to_clean["<STR_LIT:data>"]<EOL><DEDENT>return dict(<EOL>[<EOL>[k, v]<EOL>for k, v in list(to_clean.items())<EOL>if (k in allow or k not in self.temp_keys)<EOL>]<EOL>)<EOL>


full_url = "<STR_LIT>" % (self.endpoint, request)<EOL>self.self_link = request<EOL>self.request = requests.get(url=full_url, headers=self.default_headers())<EOL>self.request.encoding = "<STR_LIT:utf-8>"<EOL>try:<EOL><INDENT>self.request.raise_for_status()<EOL><DEDENT>except requests.exceptions.HTTPError:<EOL><INDENT>error_handler(self.request)<EOL><DEDENT>return self.request<EOL>

Retrieve Zotero items via the API
Combine endpoint and request to access the specific resource
Returns a JSON document


extracted = dict()<EOL>try:<EOL><INDENT>for key, value in self.request.links.items():<EOL><INDENT>parsed = urlparse(value["<STR_LIT:url>"])<EOL>fragment = "<STR_LIT>".format(path=parsed[<NUM_LIT:2>], query=parsed[<NUM_LIT:4>])<EOL>extracted[key] = fragment<EOL><DEDENT>parsed = list(urlparse(self.self_link))<EOL>stripped = "<STR_LIT:&>".join(<EOL>[<EOL>"<STR_LIT>" % (p[<NUM_LIT:0>], p[<NUM_LIT:1>])<EOL>for p in parse_qsl(parsed[<NUM_LIT:4>])<EOL>if p[<NUM_LIT:0>] != "<STR_LIT>"<EOL>]<EOL>)<EOL>extracted["<STR_LIT>"] = urlunparse(<EOL>[parsed[<NUM_LIT:0>], parsed[<NUM_LIT:1>], parsed[<NUM_LIT:2>], parsed[<NUM_LIT:3>], stripped, parsed[<NUM_LIT:5>]]<EOL>)<EOL>return extracted<EOL><DEDENT>except KeyError:<EOL><INDENT>return None<EOL><DEDENT>

Extract self, first, next, last links from a request response


def _updated(self, url, payload, template=None):

<EOL>if (<EOL>abs(<EOL>datetime.datetime.utcnow().replace(tzinfo=pytz.timezone("<STR_LIT>"))<EOL>- self.templates[template]["<STR_LIT>"]<EOL>).seconds<EOL>> <NUM_LIT><EOL>):<EOL><INDENT>query = self.endpoint + url.format(<EOL>u=self.library_id, t=self.library_type, **payload<EOL>)<EOL>headers = {<EOL>"<STR_LIT>": payload["<STR_LIT>"].strftime(<EOL>"<STR_LIT>"<EOL>)<EOL>}<EOL>headers.update(self.default_headers())<EOL>req = requests.get(query, headers=headers)<EOL>try:<EOL><INDENT>req.raise_for_status()<EOL><DEDENT>except requests.exceptions.HTTPError:<EOL><INDENT>error_handler(req)<EOL><DEDENT>return req.status_code == <NUM_LIT><EOL><DEDENT>return False<EOL>

Generic call to see if a template request returns 304
accepts:
- a string to combine with the API endpoint
- a dict of format values, in case they're required by 'url'
- a template name to check for
As per the API docs, a template less than 1 hour old is
assumed to be fresh, and will immediately return False if found


self.url_params = None<EOL>if not params.get("<STR_LIT>"):<EOL><INDENT>params["<STR_LIT>"] = "<STR_LIT>"<EOL><DEDENT>if params.get("<STR_LIT:content>"):<EOL><INDENT>params["<STR_LIT>"] = "<STR_LIT>"<EOL><DEDENT>if "<STR_LIT>" not in params or params.get("<STR_LIT>") == <NUM_LIT:0>:<EOL><INDENT>params["<STR_LIT>"] = <NUM_LIT:100><EOL><DEDENT>elif params["<STR_LIT>"] == -<NUM_LIT:1> or params["<STR_LIT>"] is None:<EOL><INDENT>del params["<STR_LIT>"]<EOL><DEDENT>if params.get("<STR_LIT>") == "<STR_LIT>":<EOL><INDENT>del params["<STR_LIT>"]<EOL><DEDENT>self.url_params = urlencode(params, doseq=True)<EOL>

Add URL parameters
Also ensure that only valid format/content combinations are requested


def _build_query(self, query_string, no_params=False):

try:<EOL><INDENT>query = quote(query_string.format(u=self.library_id, t=self.library_type))<EOL><DEDENT>except KeyError as err:<EOL><INDENT>raise ze.ParamNotPassed("<STR_LIT>" % err)<EOL><DEDENT>if no_params is False:<EOL><INDENT>if not self.url_params:<EOL><INDENT>self.add_parameters()<EOL><DEDENT>query = "<STR_LIT>" % (query, self.url_params)<EOL><DEDENT>return query<EOL>

Set request parameters. Will always add the user ID if it hasn't
been specifically set by an API method


if self.library_type != "<STR_LIT>":<EOL><INDENT>raise ze.CallDoesNotExist(<EOL>"<STR_LIT>"<EOL>)<EOL><DEDENT>query_string = "<STR_LIT>"<EOL>return self._build_query(query_string)<EOL>


query = "<STR_LIT>"<EOL>return self._totals(query)<EOL>

Return the total number of top-level items in the library


Return the count of all items in a group / library


query = "<STR_LIT>".format(<EOL>u=self.library_id, t=self.library_type, c=collection.upper()<EOL>)<EOL>return self._totals(query)<EOL>

Return the total number of items in the specified collection


query = "<STR_LIT>".format(<EOL>u=self.library_id, t=self.library_type, ta=tag<EOL>)<EOL>return self._totals(query)<EOL>

Return the total number of items for the specified tag


self.add_parameters(limit=<NUM_LIT:1>)<EOL>query = self._build_query(query)<EOL>self._retrieve_data(query)<EOL>self.url_params = None<EOL>return int(self.request.headers["<STR_LIT>"])<EOL>

General method for returning total counts


query_string = "<STR_LIT>".format(k=self.api_key)<EOL>return self._build_query(query_string)<EOL>

Retrieve info about the permissions associated with the
key associated to the given Zotero instance


query_string = "<STR_LIT>"<EOL>return self._build_query(query_string)<EOL>


@retrieve<EOL><INDENT>def fulltext_item(self, itemkey, **kwargs):<DEDENT>

query_string = "<STR_LIT>".format(<EOL>t=self.library_type, u=self.library_id, itemkey=itemkey<EOL>)<EOL>return self._build_query(query_string)<EOL>


def set_fulltext(self, itemkey, payload):

headers = self.default_headers()<EOL>headers.update({"<STR_LIT:Content-Type>": "<STR_LIT:application/json>"})<EOL>req = requests.put(<EOL>url=self.endpoint<EOL>+ "<STR_LIT>".format(<EOL>t=self.library_type, u=self.library_id, k=itemkey<EOL>),<EOL>headers=headers,<EOL>data=json.dumps(payload),<EOL>)<EOL>try:<EOL><INDENT>req.raise_for_status()<EOL><DEDENT>except requests.exceptions.HTTPError:<EOL><INDENT>error_handler(req)<EOL><DEDENT>return True<EOL>

Set full-text data for an item
<itemkey> should correspond to an existing attachment item.
payload should be a dict containing three keys:
'content': the full-text content and either
For text documents, 'indexedChars' and 'totalChars' OR
For PDFs, 'indexedPages' and 'totalPages'.


query_string = "<STR_LIT>".format(<EOL>t=self.library_type, u=self.library_id<EOL>)<EOL>headers = {"<STR_LIT>": str(version)}<EOL>headers.update(self.default_headers())<EOL>req = requests.get(self.endpoint + query_string, headers=headers)<EOL>try:<EOL><INDENT>req.raise_for_status()<EOL><DEDENT>except requests.exceptions.HTTPError:<EOL><INDENT>error_handler(req)<EOL><DEDENT>return req.json()<EOL>

Retrieve list of full-text content items and versions which are newer
than <version>


if "<STR_LIT>" not in kwargs:<EOL><INDENT>kwargs["<STR_LIT>"] = None<EOL><DEDENT>kwargs["<STR_LIT>"] = "<STR_LIT>"<EOL>return self.items(**kwargs)<EOL>

Returns dict associating items keys (all no limit by default) to versions.
Accepts a since= parameter in kwargs to limit the data to those updated since since=


if "<STR_LIT>" not in kwargs:<EOL><INDENT>kwargs["<STR_LIT>"] = None<EOL><DEDENT>kwargs["<STR_LIT>"] = "<STR_LIT>"<EOL>return self.collections(**kwargs)<EOL>

Returns dict  associating collection keys (all no limit by default) to versions.
Accepts a since= parameter in kwargs to limit the data to those updated since since=


self.items(**kwargs)<EOL>return int(self.request.headers.get("<STR_LIT>", <NUM_LIT:0>))<EOL>


if "<STR_LIT>" not in kwargs:<EOL><INDENT>kwargs["<STR_LIT>"] = None<EOL><DEDENT>query_string = "<STR_LIT>"<EOL>return self._build_query(query_string)<EOL>

Get all deleted items (requires since= parameter)


@retrieve<EOL><INDENT>def item(self, item, **kwargs):<DEDENT>

query_string = "<STR_LIT>".format(<EOL>u=self.library_id, t=self.library_type, i=item.upper()<EOL>)<EOL>return self._build_query(query_string)<EOL>


@retrieve<EOL><INDENT>def file(self, item, **kwargs):<DEDENT>

query_string = "<STR_LIT>".format(<EOL>u=self.library_id, t=self.library_type, i=item.upper()<EOL>)<EOL>return self._build_query(query_string, no_params=True)<EOL>


def dump(self, itemkey, filename=None, path=None):

if not filename:<EOL><INDENT>filename = self.item(itemkey)["<STR_LIT:data>"]["<STR_LIT:filename>"]<EOL><DEDENT>if path:<EOL><INDENT>pth = os.path.join(path, filename)<EOL><DEDENT>else:<EOL><INDENT>pth = filename<EOL><DEDENT>file = self.file(itemkey)<EOL>if self.snapshot:<EOL><INDENT>self.snapshot = False<EOL>pth = pth + "<STR_LIT>"<EOL><DEDENT>with open(pth, "<STR_LIT:wb>") as f:<EOL><INDENT>f.write(file)<EOL><DEDENT>

Dump a file attachment to disk, with optional filename and path


@retrieve<EOL><INDENT>def children(self, item, **kwargs):<DEDENT>


@retrieve<EOL><INDENT>def collection_items(self, collection, **kwargs):<DEDENT>

query_string = "<STR_LIT>".format(<EOL>u=self.library_id, t=self.library_type, c=collection.upper()<EOL>)<EOL>return self._build_query(query_string)<EOL>


@retrieve<EOL><INDENT>def collection_items_top(self, collection, **kwargs):<DEDENT>

Get a specific collection's top-level items


@retrieve<EOL><INDENT>def collection_tags(self, collection, **kwargs):<DEDENT>


@retrieve<EOL><INDENT>def collection(self, collection, **kwargs):<DEDENT>


all_collections = []<EOL>def subcoll(clct):<EOL><INDENT>"""<STR_LIT>"""<EOL>all_collections.append(clct)<EOL>if clct["<STR_LIT>"].get("<STR_LIT>", <NUM_LIT:0>) > <NUM_LIT:0>:<EOL><INDENT>[<EOL>subcoll(c)<EOL>for c in self.everything(self.collections_sub(clct["<STR_LIT:data>"]["<STR_LIT:key>"]))<EOL>]<EOL><DEDENT><DEDENT>if collid:<EOL><INDENT>toplevel = [self.collection(collid)]<EOL><DEDENT>else:<EOL><INDENT>toplevel = self.everything(self.collections_top())<EOL><DEDENT>[subcoll(collection) for collection in toplevel]<EOL>return all_collections<EOL>

Retrieve all collections and subcollections. Works for top-level collections
or for a specific collection. Works at all collection depths.


@retrieve<EOL><INDENT>def collections_sub(self, collection, **kwargs):<DEDENT>

Get subcollections for a specific collection


query_string = "<STR_LIT>"<EOL>self.tag_data = True<EOL>return self._build_query(query_string)<EOL>


@retrieve<EOL><INDENT>def item_tags(self, item, **kwargs):<DEDENT>

query_string = "<STR_LIT>".format(<EOL>u=self.library_id, t=self.library_type, i=item.upper()<EOL>)<EOL>self.tag_data = True<EOL>return self._build_query(query_string)<EOL>


return self.everything(self.top(**kwargs))<EOL>


if self.links.get("<STR_LIT>"):<EOL><INDENT>return self.links.get("<STR_LIT>")<EOL><DEDENT>else:<EOL><INDENT>raise StopIteration<EOL><DEDENT>

Return the result of the call to the URL in the 'Next' link


<EOL>if self.links is None:<EOL><INDENT>return<EOL><DEDENT>if self.links.get("<STR_LIT>"):<EOL><INDENT>yield self.follow()<EOL><DEDENT>else:<EOL><INDENT>raise StopIteration<EOL><DEDENT>


<EOL>self.links["<STR_LIT>"] = self.links["<STR_LIT>"]<EOL>return self.iterfollow()<EOL>


try:<EOL><INDENT>items = []<EOL>items.extend(query)<EOL>while self.links.get("<STR_LIT>"):<EOL><INDENT>items.extend(self.follow())<EOL><DEDENT><DEDENT>except TypeError:<EOL><INDENT>items = copy.deepcopy(query)<EOL>while self.links.get("<STR_LIT>"):<EOL><INDENT>items.entries.extend(self.follow().entries)<EOL><DEDENT><DEDENT>return items<EOL>

Retrieve all items in the library for a particular query
This method will override the 'limit' parameter if it's been set


if len(subset) > <NUM_LIT:50>:<EOL><INDENT>raise ze.TooManyItems("<STR_LIT>")<EOL><DEDENT>params = self.url_params<EOL>retr = []<EOL>for itm in subset:<EOL><INDENT>retr.extend(self.item(itm))<EOL>self.url_params = params<EOL><DEDENT>self.url_params = None<EOL>return retr<EOL>

Retrieve a subset of items
Accepts a single argument: a list of item IDs


json_kwargs = {}<EOL>if self.preserve_json_order:<EOL><INDENT>json_kwargs["<STR_LIT>"] = OrderedDict<EOL><DEDENT>try:<EOL><INDENT>items = [<EOL>json.loads(e["<STR_LIT:content>"][<NUM_LIT:0>]["<STR_LIT:value>"], **json_kwargs)<EOL>for e in retrieved.entries<EOL>]<EOL><DEDENT>except KeyError:<EOL><INDENT>return self._tags_data(retrieved)<EOL><DEDENT>return items<EOL>

Format and return data from API calls which return Items


items = []<EOL>json_kwargs = {}<EOL>if self.preserve_json_order:<EOL><INDENT>json_kwargs["<STR_LIT>"] = OrderedDict<EOL><DEDENT>for csl in retrieved.entries:<EOL><INDENT>items.append(json.loads(csl["<STR_LIT:content>"][<NUM_LIT:0>]["<STR_LIT:value>"], **json_kwargs))<EOL><DEDENT>self.url_params = None<EOL>return items<EOL>

Return a list of dicts which are dumped CSL JSON


items = []<EOL>for bib in retrieved.entries:<EOL><INDENT>items.append(bib["<STR_LIT:content>"][<NUM_LIT:0>]["<STR_LIT:value>"])<EOL><DEDENT>self.url_params = None<EOL>return items<EOL>

Return a list of strings formatted as HTML bibliography entries


items = []<EOL>for cit in retrieved.entries:<EOL><INDENT>items.append(cit["<STR_LIT:content>"][<NUM_LIT:0>]["<STR_LIT:value>"])<EOL><DEDENT>self.url_params = None<EOL>return items<EOL>

Return a list of strings formatted as HTML citation entries


self.url_params = None<EOL>return [t["<STR_LIT>"] for t in retrieved]<EOL>

Format and return data from API calls which return Tags


<EOL>template_name = "<STR_LIT>" + itemtype<EOL>query_string = "<STR_LIT>".format(i=itemtype)<EOL>if self.templates.get(template_name) and not self._updated(<EOL>query_string, self.templates[template_name], template_name<EOL>):<EOL><INDENT>return copy.deepcopy(self.templates[template_name]["<STR_LIT>"])<EOL><DEDENT>retrieved = self._retrieve_data(query_string)<EOL>return self._cache(retrieved, template_name)<EOL>


return self.item_template("<STR_LIT>" + attachment_type)<EOL>

Return a new attachment template of the required type:
imported_file
imported_url
linked_file
linked_url


def _attachment(self, payload, parentid=None):

attachment = Zupload(self, payload, parentid)<EOL>res = attachment.upload()<EOL>return res<EOL>

Create attachments
accepts a list of one or more attachment template dicts
and an optional parent Item ID. If this is specified,
attachments are created under this ID


return self.savedsearch.operators<EOL>


return self.savedsearch.conditions_operators.keys()<EOL>


<EOL>permitted_operators = self.savedsearch.conditions_operators.get(condition)<EOL>permitted_operators_list = set(<EOL>[self.savedsearch.operators.get(op) for op in permitted_operators]<EOL>)<EOL>return permitted_operators_list<EOL>

Show available operators for a given saved search condition


@ss_wrap<EOL><INDENT>def saved_search(self, name, conditions):<DEDENT>

self.savedsearch._validate(conditions)<EOL>payload = [{"<STR_LIT:name>": name, "<STR_LIT>": conditions}]<EOL>headers = {"<STR_LIT>": token()}<EOL>headers.update(self.default_headers())<EOL>req = requests.post(<EOL>url=self.endpoint<EOL>+ "<STR_LIT>".format(t=self.library_type, u=self.library_id),<EOL>headers=headers,<EOL>data=json.dumps(payload),<EOL>)<EOL>self.request = req<EOL>try:<EOL><INDENT>req.raise_for_status()<EOL><DEDENT>except requests.exceptions.HTTPError:<EOL><INDENT>error_handler(req)<EOL><DEDENT>return req.json()<EOL>

Create a saved search. conditions is a list of dicts
        containing search conditions, and must contain the following str keys:
        condition, operator, value


headers = {"<STR_LIT>": token()}<EOL>headers.update(self.default_headers())<EOL>req = requests.delete(<EOL>url=self.endpoint<EOL>+ "<STR_LIT>".format(t=self.library_type, u=self.library_id),<EOL>headers=headers,<EOL>params={"<STR_LIT>": "<STR_LIT:U+002C>".join(keys)},<EOL>)<EOL>self.request = req<EOL>try:<EOL><INDENT>req.raise_for_status()<EOL><DEDENT>except requests.exceptions.HTTPError:<EOL><INDENT>error_handler(req)<EOL><DEDENT>return req.status_code<EOL>

Delete one or more saved searches by passing a list of one or more
        unique search keys


def upload_attachments(self, attachments, parentid=None, basedir=None):

return Zupload(self, attachments, parentid, basedir=basedir).upload()<EOL>

Upload files to the already created (but never uploaded) attachments


<EOL>try:<EOL><INDENT>assert item["<STR_LIT:data>"]["<STR_LIT>"]<EOL><DEDENT>except AssertionError:<EOL><INDENT>item["<STR_LIT:data>"]["<STR_LIT>"] = list()<EOL><DEDENT>for tag in tags:<EOL><INDENT>item["<STR_LIT:data>"]["<STR_LIT>"].append({"<STR_LIT>": "<STR_LIT:%s>" % tag})<EOL><DEDENT>assert self.check_items([item])<EOL>return self.update_item(item)<EOL>

Add one or more tags to a retrieved item,
then update it on the server
Accepts a dict, and one or more tags to add to it
Returns the updated item from the server


<EOL>if self.templates.get("<STR_LIT>") and not self._updated(<EOL>"<STR_LIT>", self.templates["<STR_LIT>"], "<STR_LIT>"<EOL>):<EOL><INDENT>template = set(t["<STR_LIT>"] for t in self.templates["<STR_LIT>"]["<STR_LIT>"])<EOL><DEDENT>else:<EOL><INDENT>template = set(t["<STR_LIT>"] for t in self.item_fields())<EOL><DEDENT>template = template | set(<EOL>[<EOL>"<STR_LIT:path>",<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>"<STR_LIT:version>",<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>"<STR_LIT:filename>",<EOL>]<EOL>)<EOL>template = template | set(self.temp_keys)<EOL>for pos, item in enumerate(items):<EOL><INDENT>if set(item) == set(["<STR_LIT>", "<STR_LIT>", "<STR_LIT:version>", "<STR_LIT>", "<STR_LIT:key>", "<STR_LIT:data>"]):<EOL><INDENT>item = item["<STR_LIT:data>"]<EOL><DEDENT>to_check = set(i for i in list(item.keys()))<EOL>difference = to_check.difference(template)<EOL>if difference:<EOL><INDENT>raise ze.InvalidItemFields(<EOL>"<STR_LIT>"<EOL>% (pos + <NUM_LIT:1>, "<STR_LIT:U+0020>".join(i for i in difference))<EOL>)<EOL><DEDENT><DEDENT>return items<EOL>

Check that items to be created contain no invalid dict keys
Accepts a single argument: a list of one or more dicts
The retrieved fields are cached and re-used until a 304 call fails


<EOL>if self.templates.get("<STR_LIT>") and not self._updated(<EOL>"<STR_LIT>", self.templates["<STR_LIT>"], "<STR_LIT>"<EOL>):<EOL><INDENT>return self.templates["<STR_LIT>"]["<STR_LIT>"]<EOL><DEDENT>query_string = "<STR_LIT>"<EOL>retrieved = self._retrieve_data(query_string)<EOL>return self._cache(retrieved, "<STR_LIT>")<EOL>


def fields_types(self, tname, qstring, itemtype):

<EOL>template_name = tname + itemtype<EOL>query_string = qstring.format(i=itemtype)<EOL>if self.templates.get(template_name) and not self._updated(<EOL>query_string, self.templates[template_name], template_name<EOL>):<EOL><INDENT>return self.templates[template_name]["<STR_LIT>"]<EOL><DEDENT>retrieved = self._retrieve_data(query_string)<EOL>return self._cache(retrieved, template_name)<EOL>


return self.fields_types(<EOL>"<STR_LIT>", "<STR_LIT>", itemtype<EOL>)<EOL>


Get all available creator types for an item


def create_items(self, payload, parentid=None, last_modified=None):

if len(payload) > <NUM_LIT:50>:<EOL><INDENT>raise ze.TooManyItems("<STR_LIT>")<EOL><DEDENT>headers = {"<STR_LIT>": token(), "<STR_LIT:Content-Type>": "<STR_LIT:application/json>"}<EOL>if last_modified is not None:<EOL><INDENT>headers["<STR_LIT>"] = str(last_modified)<EOL><DEDENT>to_send = json.dumps([i for i in self._cleanup(*payload, allow=("<STR_LIT:key>"))])<EOL>headers.update(self.default_headers())<EOL>req = requests.post(<EOL>url=self.endpoint<EOL>+ "<STR_LIT>".format(t=self.library_type, u=self.library_id),<EOL>data=to_send,<EOL>headers=dict(headers),<EOL>)<EOL>self.request = req<EOL>try:<EOL><INDENT>req.raise_for_status()<EOL><DEDENT>except requests.exceptions.HTTPError:<EOL><INDENT>error_handler(req)<EOL><DEDENT>resp = req.json()<EOL>if parentid:<EOL><INDENT>uheaders = {<EOL>"<STR_LIT>": req.headers["<STR_LIT>"]<EOL>}<EOL>uheaders.update(self.default_headers())<EOL>for value in resp["<STR_LIT:success>"].values():<EOL><INDENT>payload = json.dumps({"<STR_LIT>": parentid})<EOL>presp = requests.patch(<EOL>url=self.endpoint<EOL>+ "<STR_LIT>".format(<EOL>t=self.library_type, u=self.library_id, v=value<EOL>),<EOL>data=payload,<EOL>headers=dict(uheaders),<EOL>)<EOL>self.request = presp<EOL>try:<EOL><INDENT>presp.raise_for_status()<EOL><DEDENT>except requests.exceptions.HTTPError:<EOL><INDENT>error_handler(presp)<EOL><DEDENT><DEDENT><DEDENT>return resp<EOL>

Create new Zotero items
Accepts two arguments:
    a list containing one or more item dicts
    an optional parent item ID.
Note that this can also be used to update existing items


def create_collection(self, payload, last_modified=None):

return self.create_collections(payload, last_modified)<EOL>

Alias for create_collections to preserve backward compatibility


def create_collections(self, payload, last_modified=None):

<EOL>for item in payload:<EOL><INDENT>if "<STR_LIT:name>" not in item:<EOL><INDENT>raise ze.ParamNotPassed("<STR_LIT>")<EOL><DEDENT>if "<STR_LIT>" not in item:<EOL><INDENT>item["<STR_LIT>"] = "<STR_LIT>"<EOL><DEDENT><DEDENT>headers = {"<STR_LIT>": token()}<EOL>if last_modified is not None:<EOL><INDENT>headers["<STR_LIT>"] = str(last_modified)<EOL><DEDENT>headers.update(self.default_headers())<EOL>req = requests.post(<EOL>url=self.endpoint<EOL>+ "<STR_LIT>".format(t=self.library_type, u=self.library_id),<EOL>headers=headers,<EOL>data=json.dumps(payload),<EOL>)<EOL>self.request = req<EOL>try:<EOL><INDENT>req.raise_for_status()<EOL><DEDENT>except requests.exceptions.HTTPError:<EOL><INDENT>error_handler(req)<EOL><DEDENT>return req.json()<EOL>

Create new Zotero collections
Accepts one argument, a list of dicts containing the following keys:

'name': the name of the collection
'parentCollection': OPTIONAL, the parent collection to which you wish to add this


def update_collection(self, payload, last_modified=None):

modified = payload["<STR_LIT:version>"]<EOL>if last_modified is not None:<EOL><INDENT>modified = last_modified<EOL><DEDENT>key = payload["<STR_LIT:key>"]<EOL>headers = {"<STR_LIT>": str(modified)}<EOL>headers.update(self.default_headers())<EOL>headers.update({"<STR_LIT:Content-Type>": "<STR_LIT:application/json>"})<EOL>req = requests.put(<EOL>url=self.endpoint<EOL>+ "<STR_LIT>".format(<EOL>t=self.library_type, u=self.library_id, c=key<EOL>),<EOL>headers=headers,<EOL>data=json.dumps(payload),<EOL>)<EOL>self.request = req<EOL>try:<EOL><INDENT>req.raise_for_status()<EOL><DEDENT>except requests.exceptions.HTTPError:<EOL><INDENT>error_handler(req)<EOL><DEDENT>return True<EOL>

Update a Zotero collection property such as 'name'
Accepts one argument, a dict containing collection data retrieved
using e.g. 'collections()'


def attachment_simple(self, files, parentid=None):

orig = self._attachment_template("<STR_LIT>")<EOL>to_add = [orig.copy() for fls in files]<EOL>for idx, tmplt in enumerate(to_add):<EOL><INDENT>tmplt["<STR_LIT:title>"] = os.path.basename(files[idx])<EOL>tmplt["<STR_LIT:filename>"] = files[idx]<EOL><DEDENT>if parentid:<EOL><INDENT>return self._attachment(to_add, parentid)<EOL><DEDENT>else:<EOL><INDENT>return self._attachment(to_add)<EOL><DEDENT>

Add attachments using filenames as title
Arguments:
One or more file paths to add as attachments:
An optional Item ID, which will create child attachments


def attachment_both(self, files, parentid=None):

orig = self._attachment_template("<STR_LIT>")<EOL>to_add = [orig.copy() for f in files]<EOL>for idx, tmplt in enumerate(to_add):<EOL><INDENT>tmplt["<STR_LIT:title>"] = files[idx][<NUM_LIT:0>]<EOL>tmplt["<STR_LIT:filename>"] = files[idx][<NUM_LIT:1>]<EOL><DEDENT>if parentid:<EOL><INDENT>return self._attachment(to_add, parentid)<EOL><DEDENT>else:<EOL><INDENT>return self._attachment(to_add)<EOL><DEDENT>

Add child attachments using title, filename
Arguments:
One or more lists or tuples containing title, file path
An optional Item ID, which will create child attachments


def update_item(self, payload, last_modified=None):

to_send = self.check_items([payload])[<NUM_LIT:0>]<EOL>if last_modified is None:<EOL><INDENT>modified = payload["<STR_LIT:version>"]<EOL><DEDENT>else:<EOL><INDENT>modified = last_modified<EOL><DEDENT>ident = payload["<STR_LIT:key>"]<EOL>headers = {"<STR_LIT>": str(modified)}<EOL>headers.update(self.default_headers())<EOL>req = requests.patch(<EOL>url=self.endpoint<EOL>+ "<STR_LIT>".format(<EOL>t=self.library_type, u=self.library_id, id=ident<EOL>),<EOL>headers=headers,<EOL>data=json.dumps(to_send),<EOL>)<EOL>self.request = req<EOL>try:<EOL><INDENT>req.raise_for_status()<EOL><DEDENT>except requests.exceptions.HTTPError:<EOL><INDENT>error_handler(req)<EOL><DEDENT>return True<EOL>

Update an existing item
Accepts one argument, a dict containing Item data


to_send = [self.check_items([p])[<NUM_LIT:0>] for p in payload]<EOL>headers = {}<EOL>headers.update(self.default_headers())<EOL>for chunk in chunks(to_send, <NUM_LIT:50>):<EOL><INDENT>req = requests.post(<EOL>url=self.endpoint<EOL>+ "<STR_LIT>".format(t=self.library_type, u=self.library_id),<EOL>headers=headers,<EOL>data=json.dumps(chunk),<EOL>)<EOL>self.request = req<EOL>try:<EOL><INDENT>req.raise_for_status()<EOL><DEDENT>except requests.exceptions.HTTPError:<EOL><INDENT>error_handler(req)<EOL><DEDENT>return True<EOL><DEDENT>

Update existing items
Accepts one argument, a list of dicts containing Item data


to_send = [self.check_items([p])[<NUM_LIT:0>] for p in payload]<EOL>headers = {}<EOL>headers.update(self.default_headers())<EOL>for chunk in chunks(to_send, <NUM_LIT:50>):<EOL><INDENT>req = requests.post(<EOL>url=self.endpoint<EOL>+ "<STR_LIT>".format(<EOL>t=self.library_type, u=self.library_id<EOL>),<EOL>headers=headers,<EOL>data=json.dumps(chunk),<EOL>)<EOL>self.request = req<EOL>try:<EOL><INDENT>req.raise_for_status()<EOL><DEDENT>except requests.exceptions.HTTPError:<EOL><INDENT>error_handler(req)<EOL><DEDENT>return True<EOL><DEDENT>

Update existing collections
Accepts one argument, a list of dicts containing Collection data


def addto_collection(self, collection, payload):

ident = payload["<STR_LIT:key>"]<EOL>modified = payload["<STR_LIT:version>"]<EOL>modified_collections = payload["<STR_LIT:data>"]["<STR_LIT>"] + [collection]<EOL>headers = {"<STR_LIT>": str(modified)}<EOL>headers.update(self.default_headers())<EOL>req = requests.patch(<EOL>url=self.endpoint<EOL>+ "<STR_LIT>".format(<EOL>t=self.library_type, u=self.library_id, i=ident<EOL>),<EOL>data=json.dumps({"<STR_LIT>": modified_collections}),<EOL>headers=headers,<EOL>)<EOL>self.request = req<EOL>try:<EOL><INDENT>req.raise_for_status()<EOL><DEDENT>except requests.exceptions.HTTPError:<EOL><INDENT>error_handler(req)<EOL><DEDENT>return True<EOL>

Add one or more items to a collection
Accepts two arguments:
The collection ID, and an item dict


def deletefrom_collection(self, collection, payload):

ident = payload["<STR_LIT:key>"]<EOL>modified = payload["<STR_LIT:version>"]<EOL>modified_collections = [<EOL>c for c in payload["<STR_LIT:data>"]["<STR_LIT>"] if c != collection<EOL>]<EOL>headers = {"<STR_LIT>": str(modified)}<EOL>headers.update(self.default_headers())<EOL>req = requests.patch(<EOL>url=self.endpoint<EOL>+ "<STR_LIT>".format(<EOL>t=self.library_type, u=self.library_id, i=ident<EOL>),<EOL>data=json.dumps({"<STR_LIT>": modified_collections}),<EOL>headers=headers,<EOL>)<EOL>self.request = req<EOL>try:<EOL><INDENT>req.raise_for_status()<EOL><DEDENT>except requests.exceptions.HTTPError:<EOL><INDENT>error_handler(req)<EOL><DEDENT>return True<EOL>

Delete an item from a collection
Accepts two arguments:
The collection ID, and and an item dict


if len(payload) > <NUM_LIT:50>:<EOL><INDENT>raise ze.TooManyItems("<STR_LIT>")<EOL><DEDENT>modified_tags = "<STR_LIT>".join([tag for tag in payload])<EOL>self.tags(limit=<NUM_LIT:1>)<EOL>headers = {<EOL>"<STR_LIT>": self.request.headers["<STR_LIT>"]<EOL>}<EOL>headers.update(self.default_headers())<EOL>req = requests.delete(<EOL>url=self.endpoint<EOL>+ "<STR_LIT>".format(t=self.library_type, u=self.library_id),<EOL>params={"<STR_LIT>": modified_tags},<EOL>headers=headers,<EOL>)<EOL>self.request = req<EOL>try:<EOL><INDENT>req.raise_for_status()<EOL><DEDENT>except requests.exceptions.HTTPError:<EOL><INDENT>error_handler(req)<EOL><DEDENT>return True<EOL>

Delete a group of tags
pass in up to 50 tags, or use *[tags]


def delete_item(self, payload, last_modified=None):

params = None<EOL>if isinstance(payload, list):<EOL><INDENT>params = {"<STR_LIT>": "<STR_LIT:U+002C>".join([p["<STR_LIT:key>"] for p in payload])}<EOL>if last_modified is not None:<EOL><INDENT>modified = last_modified<EOL><DEDENT>else:<EOL><INDENT>modified = payload[<NUM_LIT:0>]["<STR_LIT:version>"]<EOL><DEDENT>url = self.endpoint + "<STR_LIT>".format(<EOL>t=self.library_type, u=self.library_id<EOL>)<EOL><DEDENT>else:<EOL><INDENT>ident = payload["<STR_LIT:key>"]<EOL>if last_modified is not None:<EOL><INDENT>modified = last_modified<EOL><DEDENT>else:<EOL><INDENT>modified = payload["<STR_LIT:version>"]<EOL><DEDENT>url = self.endpoint + "<STR_LIT>".format(<EOL>t=self.library_type, u=self.library_id, c=ident<EOL>)<EOL><DEDENT>headers = {"<STR_LIT>": str(modified)}<EOL>headers.update(self.default_headers())<EOL>req = requests.delete(url=url, params=params, headers=headers)<EOL>self.request = req<EOL>try:<EOL><INDENT>req.raise_for_status()<EOL><DEDENT>except requests.exceptions.HTTPError:<EOL><INDENT>error_handler(req)<EOL><DEDENT>return True<EOL>

Delete Items from a Zotero library
Accepts a single argument:
    a dict containing item data
    OR a list of dicts containing item data


def delete_collection(self, payload, last_modified=None):

Delete a Collection from a Zotero library
Accepts a single argument:
    a dict containing item data
    OR a list of dicts containing item data


self.wait = self.wait * <NUM_LIT:2><EOL>return self.wait<EOL>


self.wait = <NUM_LIT:1><EOL>


allowed_keys = set(self.searchkeys)<EOL>operators_set = set(self.operators.keys())<EOL>for condition in conditions:<EOL><INDENT>if set(condition.keys()) != allowed_keys:<EOL><INDENT>raise ze.ParamNotPassed(<EOL>"<STR_LIT>" % "<STR_LIT:U+002CU+0020>".join(self.searchkeys)<EOL>)<EOL><DEDENT>if condition.get("<STR_LIT>") not in operators_set:<EOL><INDENT>raise ze.ParamNotPassed(<EOL>"<STR_LIT>"<EOL>% condition.get("<STR_LIT>")<EOL>)<EOL><DEDENT>permitted_operators = self.conditions_operators.get(<EOL>condition.get("<STR_LIT>")<EOL>)<EOL>permitted_operators_list = set(<EOL>[self.operators.get(op) for op in permitted_operators]<EOL>)<EOL>if condition.get("<STR_LIT>") not in permitted_operators_list:<EOL><INDENT>raise ze.ParamNotPassed(<EOL>"<STR_LIT>"<EOL>% (<EOL>condition.get("<STR_LIT>"),<EOL>condition.get("<STR_LIT>"),<EOL>"<STR_LIT:U+002CU+0020>".join(list(permitted_operators_list)),<EOL>)<EOL>)<EOL><DEDENT><DEDENT>

Validate saved search conditions, raising an error if any contain invalid operators


if not payload:  <EOL><INDENT>raise ze.ParamNotPassed<EOL><DEDENT>for templt in payload:<EOL><INDENT>if os.path.isfile(str(self.basedir.joinpath(templt["<STR_LIT:filename>"]))):<EOL><INDENT>try:<EOL><INDENT>with open(str(self.basedir.joinpath(templt["<STR_LIT:filename>"]))):<EOL><INDENT>pass<EOL><DEDENT><DEDENT>except IOError:<EOL><INDENT>raise ze.FileDoesNotExist(<EOL>"<STR_LIT>"<EOL>% str(self.basedir.joinpath(templt["<STR_LIT:filename>"]))<EOL>)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>raise ze.FileDoesNotExist(<EOL>"<STR_LIT>"<EOL>% str(self.basedir.joinpath(templt["<STR_LIT:filename>"]))<EOL>)<EOL><DEDENT><DEDENT>

ensure that all files to be attached exist
open()'s better than exists(), cos it avoids a race condition


self._verify(self.payload)<EOL>if "<STR_LIT:key>" in self.payload[<NUM_LIT:0>] and self.payload[<NUM_LIT:0>]["<STR_LIT:key>"]:<EOL><INDENT>if next((i for i in self.payload if "<STR_LIT:key>" not in i), False):<EOL><INDENT>raise ze.UnsupportedParams(<EOL>"<STR_LIT>"<EOL>)<EOL><DEDENT>return None  <EOL><DEDENT>liblevel = "<STR_LIT>"<EOL>headers = {"<STR_LIT>": token(), "<STR_LIT:Content-Type>": "<STR_LIT:application/json>"}<EOL>headers.update(self.zinstance.default_headers())<EOL>if self.parentid:<EOL><INDENT>for child in self.payload:<EOL><INDENT>child["<STR_LIT>"] = self.parentid<EOL><DEDENT><DEDENT>to_send = json.dumps(self.payload)<EOL>req = requests.post(<EOL>url=self.zinstance.endpoint<EOL>+ liblevel.format(<EOL>t=self.zinstance.library_type, u=self.zinstance.library_id<EOL>),<EOL>data=to_send,<EOL>headers=headers,<EOL>)<EOL>try:<EOL><INDENT>req.raise_for_status()<EOL><DEDENT>except requests.exceptions.HTTPError:<EOL><INDENT>error_handler(req)<EOL><DEDENT>data = req.json()<EOL>for k in data["<STR_LIT:success>"]:<EOL><INDENT>self.payload[int(k)]["<STR_LIT:key>"] = data["<STR_LIT:success>"][k]<EOL><DEDENT>return data<EOL>


def _get_auth(self, attachment, reg_key, md5=None):

mtypes = mimetypes.guess_type(attachment)<EOL>digest = hashlib.md5()<EOL>with open(attachment, "<STR_LIT:rb>") as att:<EOL><INDENT>for chunk in iter(lambda: att.read(<NUM_LIT>), b"<STR_LIT>"):<EOL><INDENT>digest.update(chunk)<EOL><DEDENT><DEDENT>auth_headers = {"<STR_LIT:Content-Type>": "<STR_LIT>"}<EOL>if not md5:<EOL><INDENT>auth_headers["<STR_LIT>"] = "<STR_LIT:*>"<EOL><DEDENT>else:<EOL><INDENT>auth_headers["<STR_LIT>"] = md5<EOL><DEDENT>auth_headers.update(self.zinstance.default_headers())<EOL>data = {<EOL>"<STR_LIT>": digest.hexdigest(),<EOL>"<STR_LIT:filename>": os.path.basename(attachment),<EOL>"<STR_LIT>": os.path.getsize(attachment),<EOL>"<STR_LIT>": str(int(os.path.getmtime(attachment) * <NUM_LIT:1000>)),<EOL>"<STR_LIT>": mtypes[<NUM_LIT:0>] or "<STR_LIT>",<EOL>"<STR_LIT>": mtypes[<NUM_LIT:1>],<EOL>"<STR_LIT>": <NUM_LIT:1>,<EOL>}<EOL>auth_req = requests.post(<EOL>url=self.zinstance.endpoint<EOL>+ "<STR_LIT>".format(<EOL>t=self.zinstance.library_type, u=self.zinstance.library_id, i=reg_key<EOL>),<EOL>data=data,<EOL>headers=auth_headers,<EOL>)<EOL>try:<EOL><INDENT>auth_req.raise_for_status()<EOL><DEDENT>except requests.exceptions.HTTPError:<EOL><INDENT>error_handler(auth_req)<EOL><DEDENT>return auth_req.json()<EOL>

Step 1: get upload authorisation for a file


def _upload_file(self, authdata, attachment, reg_key):

upload_dict = authdata[<EOL>"<STR_LIT>"<EOL>]  <EOL>upload_list = [("<STR_LIT:key>", upload_dict["<STR_LIT:key>"])]<EOL>for k in upload_dict:<EOL><INDENT>if k != "<STR_LIT:key>":<EOL><INDENT>upload_list.append((k, upload_dict[k]))<EOL><DEDENT><DEDENT>upload_list.append(("<STR_LIT:file>", open(attachment, "<STR_LIT:rb>").read()))<EOL>upload_pairs = tuple(upload_list)<EOL>try:<EOL><INDENT>upload = requests.post(<EOL>url=authdata["<STR_LIT:url>"],<EOL>files=upload_pairs,<EOL>headers={<EOL>"<STR_LIT>": "<STR_LIT>"<EOL>% __version__<EOL>},<EOL>)<EOL><DEDENT>except (requests.exceptions.ConnectionError):<EOL><INDENT>raise ze.UploadError("<STR_LIT>")<EOL><DEDENT>try:<EOL><INDENT>upload.raise_for_status()<EOL><DEDENT>except requests.exceptions.HTTPError:<EOL><INDENT>error_handler(upload)<EOL><DEDENT>return self._register_upload(authdata, reg_key)<EOL>

Step 2: auth successful, and file not on server
zotero.org/support/dev/server_api/file_upload#a_full_upload

reg_key isn't used, but we need to pass it through to Step 3


def _register_upload(self, authdata, reg_key):

reg_headers = {<EOL>"<STR_LIT:Content-Type>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT:*>",<EOL>}<EOL>reg_headers.update(self.zinstance.default_headers())<EOL>reg_data = {"<STR_LIT>": authdata.get("<STR_LIT>")}<EOL>upload_reg = requests.post(<EOL>url=self.zinstance.endpoint<EOL>+ "<STR_LIT>".format(<EOL>t=self.zinstance.library_type, u=self.zinstance.library_id, i=reg_key<EOL>),<EOL>data=reg_data,<EOL>headers=dict(reg_headers),<EOL>)<EOL>try:<EOL><INDENT>upload_reg.raise_for_status()<EOL><DEDENT>except requests.exceptions.HTTPError:<EOL><INDENT>error_handler(upload_reg)<EOL><DEDENT>

Step 3: upload successful, so register it


result = {"<STR_LIT:success>": [], "<STR_LIT>": [], "<STR_LIT>": []}<EOL>self._create_prelim()<EOL>for item in self.payload:<EOL><INDENT>if "<STR_LIT:key>" not in item:<EOL><INDENT>result["<STR_LIT>"].append(item)<EOL>continue<EOL><DEDENT>attach = str(self.basedir.joinpath(item["<STR_LIT:filename>"]))<EOL>authdata = self._get_auth(attach, item["<STR_LIT:key>"], md5=item.get("<STR_LIT>", None))<EOL>if authdata.get("<STR_LIT>"):<EOL><INDENT>result["<STR_LIT>"].append(item)<EOL>continue<EOL><DEDENT>self._upload_file(authdata, attach, item["<STR_LIT:key>"])<EOL>result["<STR_LIT:success>"].append(item)<EOL><DEDENT>return result<EOL>

File upload functionality

Goes through upload steps 0 - 3 (private class methods), and returns
a dict noting success, failure, or unchanged
(returning the payload entries with that property as a list for each status)


def __init__(self, reader, genTexts=False):

if genTexts is not None:<EOL><INDENT>self.genTexts = genTexts<EOL><DEDENT>self._reader = reader<EOL>

Creates an instance of *Borrower* class.

           Args:
               reader: a *reader* object

           Keyword Args:
               genText: indicates whether this borrower should be looking
                        for transformed MIBs that include human-oriented texts


def __init__(self, parser, codegen, writer):

self._parser = parser<EOL>self._codegen = codegen<EOL>self._symbolgen = SymtableCodeGen()<EOL>self._writer = writer<EOL>self._sources = []<EOL>self._searchers = []<EOL>self._borrowers = []<EOL>

Creates an instance of *MibCompiler* class.

           Args:
               parser: ASN.1 MIB parser object
               codegen: MIB transformation object
               writer: transformed MIB storing object


self._sources.extend(sources)<EOL>debug.logger & debug.flagCompiler and debug.logger(<EOL>'<STR_LIT>' % '<STR_LIT:U+002CU+0020>'.join([str(x) for x in self._sources]))<EOL>return self<EOL>

Add more ASN.1 MIB source repositories.

        MibCompiler.compile will invoke each of configured source objects
        in order of their addition asking each to fetch MIB module specified
        by name.

        Args:
            sources: reader object(s)

        Returns:
            reference to itself (can be used for call chaining)


self._searchers.extend(searchers)<EOL>debug.logger & debug.flagCompiler and debug.logger(<EOL>'<STR_LIT>' % '<STR_LIT:U+002CU+0020>'.join([str(x) for x in self._searchers]))<EOL>return self<EOL>

Add more transformed MIBs repositories.

        MibCompiler.compile will invoke each of configured searcher objects
        in order of their addition asking each if already transformed MIB
        module already exists and is more recent than specified.

        Args:
            searchers: searcher object(s)

        Returns:
            reference to itself (can be used for call chaining)


self._borrowers.extend(borrowers)<EOL>debug.logger & debug.flagCompiler and debug.logger(<EOL>'<STR_LIT>' % '<STR_LIT:U+002CU+0020>'.join([str(x) for x in self._borrowers]))<EOL>return self<EOL>

Add more transformed MIBs repositories to borrow MIBs from.

        Whenever MibCompiler.compile encounters MIB module which neither of
        the *searchers* can find or fetched ASN.1 MIB module can not be
        parsed (due to syntax errors), these *borrowers* objects will be
        invoked in order of their addition asking each if already transformed
        MIB can be fetched (borrowed).

        Args:
            borrowers: borrower object(s)

        Returns:
            reference to itself (can be used for call chaining)