コード例 #1
0
def _create_schema(id_: str, schema_content: SchemaContent,
                   rossum: RossumClient, name: Optional[str]) -> None:
    original_schema = get_json(rossum.get(f"schemas/{id_}"))
    new_schema = rossum.create_schema(name or original_schema["name"],
                                      schema_content)

    for queue_url in original_schema["queues"]:
        if queue_url.startswith(rossum.url):
            queue_url = queue_url[len(rossum.url) + 1:]
        rossum.patch(queue_url, data={"schema": new_schema["url"]})
コード例 #2
0
def get_data(
    ctx: click.Context,
    queue_id: int,
    files: Tuple[str],
    indent: int,
    ensure_ascii: bool,
    format_: str,
    output_file: Optional[IO[str]],
):
    annotations_to_export = list()

    with RossumClient(context=ctx.obj) as rossum:
        for file in files:
            json_response = rossum.upload_document(queue_id, file)
            annotation_id = get_id(json_response)
            annotations_to_export.append(annotation_id)
            rossum.poll_annotation(annotation_id, _is_done)

        export_data = rossum.export_data(queue_id, annotations_to_export,
                                         format_)

        if format_ == "json":
            output = json.dumps(get_json(export_data),
                                indent=indent,
                                ensure_ascii=ensure_ascii)
        else:
            output = get_text(export_data)
        click.echo(output.encode("utf-8"), file=output_file, nl=False)
コード例 #3
0
ファイル: user_assignment.py プロジェクト: qiq/rossum
def list_command(ctx: click.Context, user_ids: Tuple[int],
                 queue_ids: Tuple[int]) -> None:
    """List all users and their assignments to queues."""
    with RossumClient(context=ctx.obj) as rossum:
        queue_users = rossum.get_queues((USERS, ), users=user_ids)

    user_queues: Dict[int, List[List[Optional[str]]]] = {}
    for queue in queue_users:
        if queue_ids and int(queue["id"]) not in queue_ids:
            continue
        for user in queue["users"]:
            user_id = int(user["id"])
            if user_ids and user_id not in user_ids:
                continue

            if user_id not in user_queues:
                user_queues[user_id] = [[
                    user["id"], user["username"], queue["id"], queue["name"]
                ]]
            else:
                user_queues[user_id].append(
                    [None, None, queue["id"], queue["name"]])
    user_queues = dict(sorted(user_queues.items()))
    click.echo(
        tabulate(
            chain.from_iterable(user_queues.values()),
            headers=["id", "username", "queue id", "queue name"],
        ))
コード例 #4
0
def list_command(ctx: click.Context, ):
    with RossumClient(context=ctx.obj) as rossum:
        hooks_list = rossum.get_hooks((QUEUES, ))

    headers = ["id", "name", "events", "queues", "active", "sideload"]

    def get_row(hook: dict) -> List[str]:
        fields = [
            hook["id"],
            hook["name"],
            ", ".join(e for e in hook["events"]),
            ", ".join(str(q.get("id", "")) for q in hook["queues"]),
            hook["active"],
            hook["sideload"],
        ]

        additional = ["url", "insecure_ssl", "secret"]

        for field in additional:
            if field in hook["config"]:
                fields.append(hook["config"][field])

        for header in additional:
            if header not in headers:
                headers.append(header)

        hook_list = [item for item in fields]
        return hook_list

    table = [get_row(hook) for hook in hooks_list]

    click.echo(tabulate(table, headers=headers))
コード例 #5
0
ファイル: connector.py プロジェクト: qiq/rossum
def change_command(
    ctx: click.Context,
    id_: str,
    queue_ids: Tuple[int],
    name: Optional[str],
    service_url: str,
    auth_token: str,
    params: Optional[str],
    asynchronous: Optional[bool],
) -> None:
    if not any([queue_ids, service_url, auth_token, params, asynchronous]):
        return

    data: Dict[str, Any] = {}

    with RossumClient(context=ctx.obj) as rossum:
        if queue_ids:
            data["queues"] = [
                rossum.get_queue(queue)["url"] for queue in queue_ids
            ]
        if name is not None:
            data["name"] = name
        if service_url is not None:
            data["service_url"] = service_url
        if auth_token is not None:
            data["authorization_token"] = auth_token
        if params is not None:
            data["params"] = params
        if asynchronous is not None:
            data["asynchronous"] = asynchronous

        rossum.patch(f"connectors/{id_}", data)
コード例 #6
0
ファイル: connector.py プロジェクト: qiq/rossum
def create_command(
    ctx: click.Context,
    name: str,
    queue_ids: Tuple[int, ...],
    service_url: str,
    auth_token: str,
    params: Optional[str],
    asynchronous: Optional[bool],
) -> None:
    token = auth_token or _generate_token()

    with RossumClient(context=ctx.obj) as rossum:
        if not queue_ids:
            queue_urls = [rossum.get_queue()["url"]]
        else:
            queue_urls = []
            for id_ in queue_ids:
                queue_dict = rossum.get_queue(id_)
                if queue_dict:
                    queue_urls.append(queue_dict["url"])

        response = rossum.create_connector(
            name=name,
            queues=queue_urls,
            service_url=service_url,
            authorization_token=token,
            params=params,
            asynchronous=asynchronous,
        )
        click.echo(
            f"{response['id']}, {response['name']}, {response['queues']}")
コード例 #7
0
ファイル: user.py プロジェクト: qiq/rossum
def create_command(
    ctx: click.Context,
    username: str,
    password: Optional[str],
    queue_ids: Tuple[int],
    organization_id: Optional[int],
    group: str,
    locale: str,
) -> None:
    """
    Create user with USERNAME and add him to QUEUES specified by ids.
    """
    password = password or generate_secret()
    with RossumClient(context=ctx.obj) as rossum:
        if rossum.get_users(username=username):
            raise click.ClickException(f"User with username {username} already exists.")
        organization = rossum.get_organization(organization_id)

        workspaces = rossum.get_workspaces(organization=organization["id"], sideloads=(QUEUES,))
        queues = chain.from_iterable(w[str(QUEUES)] for w in workspaces)
        queue_urls = [q["url"] for q in queues if q["id"] in queue_ids]

        response = rossum.create_user(
            username, organization["url"], queue_urls, password, group, locale
        )
        click.echo(f"{response['id']}, {password}")
コード例 #8
0
class TestRetryMechanism:
    api_client = RossumClient(None,
                              retry_logic_rules={
                                  "attempts": 2,
                                  "wait_s": 0.1
                              })

    @pytest.mark.usefixtures("mock_login_request")
    def test_retry_logic_if_api_responds_with_502(self, requests_mock):
        user_json = {"user": 123}
        get_user_called = requests_mock.get(
            f"{API_URL}/v1/auth/user",
            [
                {
                    "exc":
                    requests.exceptions.ConnectionError("Connection refused")
                },
                {
                    "json": user_json,
                    "status_code": 200
                },
            ],
        )
        assert user_json == self.api_client.get_user()
        assert get_user_called.call_count == 2
コード例 #9
0
ファイル: connector.py プロジェクト: qiq/rossum
def list_command(ctx: click.Context, ):
    with RossumClient(context=ctx.obj) as rossum:
        connectors_list = rossum.get_connectors((QUEUES, ))

    headers = ["id", "name", "service url", "queues", "params", "asynchronous"]

    def get_row(connector: dict) -> List[str]:
        res = [
            connector["id"],
            connector["name"],
            connector["service_url"],
            ", ".join(str(q.get("id", "")) for q in connector["queues"]),
            connector["params"],
            connector["asynchronous"],
        ]
        try:
            token = connector["authorization_token"]
        except KeyError:
            pass
        else:
            res.append(token)
            if "authorization_token" not in headers:
                headers.append("authorization_token")

        return res

    table = [get_row(connector) for connector in connectors_list]

    click.echo(tabulate(table, headers=headers))
コード例 #10
0
def upload_command(ctx: click.Context, id_: str, schema_content: List[dict],
                   rewrite: bool, name: Optional[str]):
    """
    Update schema in ROSSUM.
    """
    upload_func = _rewrite_schema if rewrite else _create_schema
    with RossumClient(context=ctx.obj) as rossum:
        upload_func(id_, schema_content, rossum, name)
コード例 #11
0
ファイル: workspace.py プロジェクト: qiq/rossum
def create_command(ctx: click.Context, name: str,
                   organization_id: Optional[int]) -> None:
    with RossumClient(context=ctx.obj) as rossum:
        organization_url = rossum.get_organization(organization_id)["url"]

        workspace_response = rossum.create_workspace(name, organization_url)

    click.echo(workspace_response["id"])
コード例 #12
0
ファイル: queue.py プロジェクト: qiq/rossum
def change_command(
    ctx: click.Context,
    id_: int,
    name: Optional[str],
    schema_content: Optional[List[dict]],
    email_prefix: Optional[str],
    bounce_email: Optional[str],
    connector_id: Optional[int],
    hook_id: Optional[Tuple[int, ...]],
    locale: Optional[str],
) -> None:

    if not any([
            name, schema_content, email_prefix, bounce_email, connector_id,
            locale, hook_id
    ]):
        return

    data: Dict[str, Any] = {}

    if name is not None:
        data["name"] = name

    if locale is not None:
        data["locale"] = locale

    with RossumClient(context=ctx.obj) as rossum:
        if email_prefix or bounce_email:
            queue_dict = rossum.get_queue(id_)
            if not queue_dict["inbox"]:
                inbox_dict = _create_inbox(rossum, queue_dict, email_prefix,
                                           bounce_email, name)
            else:
                inbox_dict = _patch_inbox(rossum, queue_dict, email_prefix,
                                          bounce_email)
            click.echo(
                f"{inbox_dict['id']}, {inbox_dict['email']}, {inbox_dict['bounce_email_to']}"
            )

        if connector_id is not None:
            data["connector"] = get_json(
                rossum.get(f"connectors/{connector_id}"))["url"]

        if hook_id:
            hooks_urls = []
            for hook in hook_id:
                hook_url = get_json(rossum.get(f"hooks/{hook}"))["url"]
                hooks_urls.append(hook_url)
                data["hooks"] = hooks_urls

        if schema_content is not None:
            name = name or rossum.get_queue(id_)["name"]
            schema_dict = rossum.create_schema(f"{name} schema",
                                               schema_content)
            data["schema"] = schema_dict["url"]

        if data:
            rossum.patch(f"queues/{id_}", data)
コード例 #13
0
def change_command(
    ctx: click.Context,
    id_: int,
    queue_ids: Tuple[int, ...],
    name: Optional[str],
    hook_type: str,
    events: Tuple[str, ...],
    active: Optional[bool],
    sideload: Tuple[str, ...],
    token_owner: Optional[int],
    run_after: List[str] = None,
    test: Optional[str] = None,
    **kwargs,
) -> None:

    config = {**kwargs}
    config = cleanup_config(config)

    if not any([queue_ids, name, active, events, sideload, config]):
        return

    data: Dict[str, Any] = {"config": {}}

    with RossumClient(context=ctx.obj) as rossum:
        if queue_ids:
            data["queues"] = [
                rossum.get_queue(queue)["url"] for queue in queue_ids
            ]
        if name is not None:
            data["name"] = name
        if hook_type:
            data["type"] = hook_type
        if active is not None:
            data["active"] = active
        if events:
            data["events"] = list(events)
        if config:
            data["config"] = config
        if sideload:
            data["sideload"] = list(sideload)
        if token_owner:
            data["token_owner"] = f"{rossum.url}/users/{token_owner}"
        if run_after:
            data["run_after"] = [
                f"{rossum.url}/hooks/{hook_id}" for hook_id in run_after
            ]
        if test:
            try:
                loaded_test = json.loads(test)
                data["test"] = loaded_test
            except JSONDecodeError:
                click.echo(
                    "Could not parse value for --test. Did you pass a valid JSON?"
                )
                return

        rossum.patch(f"hooks/{id_}", data)
コード例 #14
0
ファイル: queue.py プロジェクト: qiq/rossum
def _create_inbox(
    rossum: RossumClient,
    queue_dict: dict,
    email_prefix: Optional[str],
    bounce_email: Optional[str],
    name: Optional[str],
) -> dict:
    return rossum.create_inbox(f"{name or queue_dict['name']} inbox",
                               email_prefix, bounce_email, queue_dict["url"])
コード例 #15
0
ファイル: user_assignment.py プロジェクト: qiq/rossum
def remove_command(ctx: click.Context, user_ids: Tuple[int],
                   queue_ids: Tuple[int]) -> None:
    with RossumClient(context=ctx.obj) as rossum:
        for user_id in user_ids:
            queues = rossum.get_queues(users=[user_id])
            new_queues = [
                q["url"] for q in queues if int(q["id"]) not in queue_ids
            ]
            rossum.patch(f"{USERS}/{user_id}", {str(QUEUES): new_queues})
コード例 #16
0
ファイル: user_assignment.py プロジェクト: qiq/rossum
def add_command(ctx: click.Context, user_ids: Tuple[int],
                queue_ids: Tuple[int]) -> None:
    with RossumClient(context=ctx.obj) as rossum:
        for user_id in user_ids:
            user = rossum.get_user(user_id)
            new_queues = user["queues"] + [
                rossum.get_queue(q_id)["url"] for q_id in queue_ids
            ]
            rossum.patch(f"{USERS}/{user_id}", {str(QUEUES): new_queues})
コード例 #17
0
ファイル: commands.py プロジェクト: qiq/rossum
def list_command(ctx: click.Context, ):
    with RossumClient(context=ctx.obj) as rossum:
        schemas = rossum.get_schemas((QUEUES, ))

    table = [[
        schema["id"], schema["name"],
        ", ".join(str(s.get("id", "")) for s in schema["queues"])
    ] for schema in schemas]

    click.echo(tabulate(table, headers=["id", "name", "queues"]))
コード例 #18
0
ファイル: workspace.py プロジェクト: qiq/rossum
def change_command(ctx: click.Context, id_: str, name: Optional[str]) -> None:
    if not any([name]):
        return

    data: Dict[str, Any] = {}
    if name is not None:
        data["name"] = name

    with RossumClient(context=ctx.obj) as rossum:
        rossum.patch(f"workspaces/{id_}", data)
コード例 #19
0
ファイル: workspace.py プロジェクト: qiq/rossum
def list_command(ctx: click.Context, ):
    with RossumClient(context=ctx.obj) as rossum:
        workspaces = rossum.get_workspaces((QUEUES, ))

    table = [[
        workspace["id"],
        workspace["name"],
        ", ".join(str(q.get("id", "")) for q in workspace["queues"]),
    ] for workspace in workspaces]

    click.echo(tabulate(table, headers=["id", "name", "queues"]))
コード例 #20
0
ファイル: queue.py プロジェクト: qiq/rossum
def _patch_inbox(rossum: RossumClient, queue_dict: dict,
                 email_prefix: Optional[str],
                 bounce_email: Optional[str]) -> dict:
    inbox_data: Dict[str, Any] = {}

    if email_prefix:
        inbox_data["email_prefix"] = email_prefix

    if bounce_email:
        inbox_data["bounce_email_to"] = bounce_email
        inbox_data["bounce_unprocessable_attachments"] = True

    _, inbox_id = queue_dict["inbox"].rsplit("/", 1)
    return get_json(rossum.patch(f"inboxes/{inbox_id}", inbox_data))
コード例 #21
0
ファイル: user.py プロジェクト: qiq/rossum
def list_command(ctx: click.Context,):
    with RossumClient(context=ctx.obj) as rossum:
        users_list = rossum.get_users((QUEUES, GROUPS), is_active=True)

    table = [
        [
            user["id"],
            user["username"],
            ", ".join(str(g["name"]) for g in user[str(GROUPS)]),
            ", ".join(str(q["id"]) for q in user[str(QUEUES)]),
        ]
        for user in users_list
    ]

    click.echo(tabulate(table, headers=["id", "username", "groups", "queues"]))
コード例 #22
0
ファイル: user.py プロジェクト: qiq/rossum
def change_command(
    ctx: click.Context, id_: int, queue_ids: Tuple[int], group: Optional[str], locale: Optional[str]
) -> None:
    if not any([queue_ids, group, locale]):
        return

    data: Dict[str, Any] = {}

    with RossumClient(context=ctx.obj) as rossum:
        if queue_ids:
            data[str(QUEUES)] = [rossum.get_queue(queue)["url"] for queue in queue_ids]
        if group is not None:
            data[str(GROUPS)] = [g["url"] for g in rossum.get_groups(group_name=group)]
        if locale is not None:
            ui_settings = rossum.get_user(id_)["ui_settings"]
            data["ui_settings"] = {**ui_settings, "locale": locale}

        rossum.patch(f"{USERS}/{id_}", data)
コード例 #23
0
ファイル: workspace.py プロジェクト: qiq/rossum
def delete_command(ctx: click.Context, id_: int) -> None:
    with RossumClient(context=ctx.obj) as rossum:
        workspace = rossum.get_workspace(id_)
        queues = rossum.get_queues(workspace=workspace["id"])
        documents = {}
        for queue in queues:
            res, _ = rossum.get_paginated(
                "annotations",
                {
                    "page_size": 50,
                    "queue": queue["id"],
                    "sideload": "documents"
                },
                key="documents",
            )
            documents.update({d["id"]: d["url"] for d in res})

        rossum.delete({workspace["id"]: workspace["url"], **documents})
コード例 #24
0
ファイル: hook.py プロジェクト: qiq/rossum
def create_command(
    ctx: click.Context,
    name: str,
    hook_type: str,
    queue_ids: Tuple[int, ...],
    active: bool,
    events: Tuple[str, ...],
    sideload: Tuple[str, ...],
    **kwargs,
) -> None:

    with RossumClient(context=ctx.obj) as rossum:
        if not queue_ids:
            queue_urls = [rossum.get_queue()["url"]]
        else:
            queue_urls = []
            for id_ in queue_ids:
                queue_dict = rossum.get_queue(id_)
                if queue_dict:
                    queue_urls.append(queue_dict["url"])

        config = {**kwargs}
        config = cleanup_config(config)

        response = rossum.create_hook(
            name=name,
            hook_type=hook_type,
            queues=queue_urls,
            active=active,
            events=list(events),
            sideload=list(sideload),
            config=config,
        )

        additional_fields = [
            value for key, value in response["config"].items()
            if key not in ["code", "runtime", "insecure_ssl"]
        ]

        regular_fields = f"{response['id']}, {response['name']}, {response['queues']}, {response['events']}, {response['sideload']}"
        click.echo(regular_fields + ", " +
                   f"{', '.join(map(str, additional_fields))}"
                   if additional_fields != [] else regular_fields)
コード例 #25
0
ファイル: hook.py プロジェクト: qiq/rossum
def change_command(
    ctx: click.Context,
    id_: int,
    queue_ids: Tuple[int, ...],
    name: Optional[str],
    hook_type: str,
    events: Tuple[str, ...],
    active: Optional[bool],
    sideload: Tuple[str, ...],
    **kwargs,
) -> None:

    config = {**kwargs}
    config = cleanup_config(config)

    if not any([queue_ids, name, active, events, sideload, config]):
        return

    data: Dict[str, Any] = {"config": {}}

    with RossumClient(context=ctx.obj) as rossum:
        if queue_ids:
            data["queues"] = [
                rossum.get_queue(queue)["url"] for queue in queue_ids
            ]
        if name is not None:
            data["name"] = name
        if hook_type:
            data["type"] = hook_type
        if active is not None:
            data["active"] = active
        if events:
            data["events"] = list(events)
        if config:
            data["config"] = config
        if sideload:
            data["sideload"] = list(sideload)

        rossum.patch(f"hooks/{id_}", data)
コード例 #26
0
ファイル: queue.py プロジェクト: qiq/rossum
def create_command(
    ctx: click.Context,
    name: str,
    schema_content: List[dict],
    email_prefix: Optional[str],
    bounce_email: Optional[str],
    workspace_id: Optional[int],
    connector_id: Optional[int],
    hook_id: Optional[Tuple[int, ...]],
    locale: Optional[str],
) -> None:
    if email_prefix is not None and bounce_email is None:
        raise click.ClickException(
            "Inbox cannot be created without specified bounce email.")

    with RossumClient(context=ctx.obj) as rossum:
        workspace_url = rossum.get_workspace(workspace_id)["url"]
        connector_url = (get_json(
            rossum.get(f"connectors/{connector_id}"))["url"]
                         if connector_id is not None else None)

        hooks_urls = []
        if hook_id:
            for hook in hook_id:
                hook_url = get_json(rossum.get(f"hooks/{hook}"))["url"]
                hooks_urls.append(hook_url)

        schema_dict = rossum.create_schema(f"{name} schema", schema_content)
        queue_dict = rossum.create_queue(name, workspace_url,
                                         schema_dict["url"], connector_url,
                                         hooks_urls, locale)

        inbox_dict = {"email": "no email-prefix specified"}
        if email_prefix is not None:
            inbox_dict = rossum.create_inbox(f"{name} inbox", email_prefix,
                                             bounce_email, queue_dict["url"])
    click.echo(f"{queue_dict['id']}, {inbox_dict['email']}")
コード例 #27
0
ファイル: queue.py プロジェクト: qiq/rossum
def list_command(ctx: click.Context, ) -> None:
    with RossumClient(context=ctx.obj) as rossum:
        queues = rossum.get_queues(
            (WORKSPACES, INBOXES, SCHEMAS, USERS, HOOKS))

    table = [[
        queue["id"],
        queue["name"],
        str(queue["workspace"].get("id", "")),
        queue["inbox"].get("email", ""),
        str(queue["schema"].get("id", "")),
        ", ".join(str(q.get("id", "")) for q in queue["users"]),
        queue["connector"],
        ", ".join(str(q.get("id", "")) for q in queue["hooks"]),
    ] for queue in queues]

    click.echo(
        tabulate(
            table,
            headers=[
                "id", "name", "workspace", "inbox", "schema", "users",
                "connector", "hooks"
            ],
        ))
コード例 #28
0
def create_command(
    ctx: click.Context,
    name: str,
    hook_type: str,
    queue_ids: Tuple[int, ...],
    active: bool,
    events: Tuple[str, ...],
    sideload: Tuple[str, ...],
    token_owner: Optional[int],
    run_after: List[str] = None,
    test: Optional[str] = None,
    **kwargs,
) -> None:

    with RossumClient(context=ctx.obj) as rossum:
        if not queue_ids:
            queue_urls = [rossum.get_queue()["url"]]
        else:
            queue_urls = []
            for id_ in queue_ids:
                queue_dict = rossum.get_queue(id_)
                if queue_dict:
                    queue_urls.append(queue_dict["url"])

        config = {**kwargs}
        config = cleanup_config(config)

        token_owner_url = f"{rossum.url}/users/{token_owner}" if token_owner else None
        all_run_after_hooks = (
            [f"{rossum.url}/hooks/{hook_id}"
             for hook_id in run_after] if run_after else [])

        try:
            loaded_test = json.loads(test) if test else {}
        except JSONDecodeError:
            click.echo(
                "Could not parse value for --test. Did you pass a valid JSON?")
            return

        response = rossum.create_hook(
            name=name,
            hook_type=hook_type,
            queues=queue_urls,
            active=active,
            events=list(events),
            sideload=list(sideload),
            config=config,
            token_owner=token_owner_url,
            run_after=all_run_after_hooks,
            test=loaded_test,
        )

        additional_fields = [
            value for key, value in response["config"].items()
            if key not in ["code", "runtime", "insecure_ssl"]
        ]

        regular_fields = f"{response['id']}, {response['name']}, {response['queues']}, {response['events']}, {response['sideload']}"
        click.echo(regular_fields + ", " +
                   f"{', '.join(map(str, additional_fields))}"
                   if additional_fields != [] else regular_fields)
コード例 #29
0
ファイル: connector.py プロジェクト: qiq/rossum
def delete_command(ctx: click.Context, id_: str) -> None:
    with RossumClient(context=ctx.obj) as rossum:
        url = rossum.url
        rossum.delete(to_delete={f"{id_}": f"{url}/connectors/{id_}"},
                      item="connector")
コード例 #30
0
ファイル: password.py プロジェクト: qiq/rossum
def reset_command(ctx: click.Context, email: str) -> None:
    with RossumClient(context=ctx.obj) as rossum:
        result = rossum.reset_user_password(email)
        click.echo(result.get("detail"))