async def test_create_snapshot_workflow(client, user_project: ProjectDict):

    project_uuid = user_project["uuid"]

    # get existing project
    resp = await client.get(f"/{vtag}/projects/{project_uuid}")
    data, _ = await assert_status(resp, web.HTTPOk)

    assert data
    project = Project.parse_obj(data)

    # list snapshots -> None
    resp = await client.get(f"/{vtag}/projects/{project_uuid}/snapshots")
    data, _ = await assert_status(resp, web.HTTPOk)

    assert data == []

    # create snapshot
    resp = await client.post(f"/{vtag}/projects/{project_uuid}/snapshots")
    data, _ = await assert_status(resp, web.HTTPCreated)

    assert data
    snapshot = SnapshotItem.parse_obj(data)

    assert snapshot.parent_uuid == project.uuid

    # snapshot has an associated project
    resp = await client.get(f"/{vtag}/projects/{snapshot.project_uuid}")
    data, _ = await assert_status(resp, web.HTTPOk)

    assert data
    snapshot_project = Project.parse_obj(data)

    # FIXME: project is None and snapshot_project is {}
    project.ui.workbench = {}
    project.ui.slideshow = {}

    different_fields = {"name", "uuid", "creation_date", "last_change_date"}
    assert snapshot_project.dict(
        exclude=different_fields, exclude_none=True, exclude_unset=True
    ) == project.dict(exclude=different_fields, exclude_none=True, exclude_unset=True)

    # snapshot projects are hidden, and therefore NOT listed
    resp = await client.get(f"/{vtag}/projects")
    data, _ = await assert_status(resp, web.HTTPOk)

    assert len(data) == 1

    # FIXME:
    project.ui.workbench = None
    project.ui.slideshow = None
    assert project == Project.parse_obj(data[0])

    # now it has one snapshot
    resp = await client.get(f"/{vtag}/projects/{project_uuid}/snapshots")
    data, _ = await assert_status(resp, web.HTTPOk)

    assert len(data) == 1
    assert snapshot == SnapshotItem.parse_obj(data[0])
예제 #2
0
def test_project_with_thumbnail_as_empty_string(minimal_project: Dict[str,
                                                                      Any]):
    thumbnail_empty_string = deepcopy(minimal_project)
    thumbnail_empty_string.update({"thumbnail": ""})
    project = Project.parse_obj(thumbnail_empty_string)

    assert project
    assert project.thumbnail == None
예제 #3
0
async def take_snapshot(
    parent: ProjectDict,
    snapshot_label: Optional[str] = None,
) -> Tuple[ProjectDict, Snapshot]:

    assert Project.parse_obj(parent)  # nosec

    # Clones parent's project document
    snapshot_timestamp: datetime = parent["lastChangeDate"]
    snapshot_project_uuid: UUID = Snapshot.compose_project_uuid(
        parent["uuid"], snapshot_timestamp
    )

    child: ProjectDict
    child, _ = projects_utils.clone_project_document(
        project=parent,
        forced_copy_project_id=snapshot_project_uuid,
    )

    assert child  # nosec
    assert Project.parse_obj(child)  # nosec

    child["name"] += snapshot_label or f" [snapshot {snapshot_timestamp}]"
    # creation_date = state of parent upon copy! WARNING: changes can be state changes and not project definition?
    child["creationDate"] = snapshot_timestamp
    child["hidden"] = True
    child["published"] = False

    snapshot = Snapshot(
        name=snapshot_label or f"Snapshot {snapshot_timestamp} [{parent['name']}]",
        created_at=snapshot_timestamp,
        parent_uuid=parent["uuid"],
        project_uuid=child["uuid"],
    )

    return (child, snapshot)
async def test_create_snapshot(client, user_project: ProjectDict):

    project_uuid = user_project["uuid"]

    # create snapshot
    resp = await client.post(f"/{vtag}/projects/{project_uuid}/snapshots")
    data, _ = await assert_status(resp, web.HTTPCreated)

    assert data
    snapshot = SnapshotItem.parse_obj(data)

    assert str(snapshot.parent_uuid) == project_uuid

    # snapshot project can be now retrieved
    resp = await client.get(f"/{vtag}/projects/{snapshot.project_uuid}")
    data, _ = await assert_status(resp, web.HTTPOk)

    assert data
    snapshot_project = Project.parse_obj(data)
    assert snapshot_project.uuid == snapshot.project_uuid
async def test_take_snapshot(user_project: ProjectDict):

    project, snapshot = await take_snapshot(parent=user_project,
                                            snapshot_label="some snapshot")

    assert isinstance(project, dict)
    assert isinstance(snapshot, Snapshot)

    # project overrides ORM-only fields
    assert project["hidden"]
    assert not project["published"]

    # domain models
    parent = Project.parse_obj(user_project)

    # snapshot timestamp corresponds to the last change of the project
    def to_dt(timestamp):
        return datetime.fromisoformat(
            timestamp[:-1]).replace(tzinfo=timezone.utc)

    assert snapshot.created_at == to_dt(parent.last_change_date)
    assert to_dt(project["creationDate"]) == snapshot.created_at
예제 #6
0
async def test_workflow(
    client: TestClient,
    user_project: ProjectDict,
    do_update_user_project: Callable[[UUID], Awaitable],
):

    project_uuid = user_project["uuid"]

    # get existing project
    resp = await client.get(f"/{vtag}/projects/{project_uuid}")
    data, _ = await assert_status(resp, web.HTTPOk)
    project = Project.parse_obj(data)
    assert project.uuid == UUID(project_uuid)

    #
    # list repos i.e. versioned projects
    resp = await client.get(f"/{vtag}/repos/projects")
    data, _ = await assert_status(resp, web.HTTPOk)

    assert data == []

    #
    # CREATE a checkpoint
    resp = await client.post(
        f"/{vtag}/repos/projects/{project_uuid}/checkpoints",
        json={
            "tag": "v1",
            "message": "init"
        },
    )
    data, _ = await assert_status(resp, web.HTTPCreated)

    assert data
    checkpoint1 = CheckpointApiModel.parse_obj(
        data)  # NOTE: this is NOT API model

    #
    # this project now has a repo
    resp = await client.get(f"/{vtag}/repos/projects")
    page = await assert_resp_page(resp, expected_total=1, expected_count=1)

    repo = RepoApiModel.parse_obj(page.data[0])
    assert repo.project_uuid == UUID(project_uuid)

    # GET checkpoint with HEAD
    resp = await client.get(
        f"/{vtag}/repos/projects/{project_uuid}/checkpoints/HEAD")
    data, _ = await assert_status(resp, web.HTTPOk)
    assert CheckpointApiModel.parse_obj(data) == checkpoint1

    # TODO: GET checkpoint with tag
    with pytest.raises(aiohttp.ClientResponseError) as excinfo:
        resp = await client.get(
            f"/{vtag}/repos/projects/{project_uuid}/checkpoints/v1")
        resp.raise_for_status()
        assert CheckpointApiModel.parse_obj(data) == checkpoint1

    assert excinfo.value.status == web.HTTPNotImplemented.status_code

    # GET checkpoint with id
    resp = await client.get(
        f"/{vtag}/repos/projects/{project_uuid}/checkpoints/{checkpoint1.id}")
    assert str(resp.url) == checkpoint1.url
    assert CheckpointApiModel.parse_obj(data) == checkpoint1

    # LIST checkpoints
    resp = await client.get(
        f"/{vtag}/repos/projects/{project_uuid}/checkpoints")
    page = await assert_resp_page(resp, expected_total=1, expected_count=1)

    assert CheckpointApiModel.parse_obj(page.data[0]) == checkpoint1

    # UPDATE checkpoint annotations
    resp = await client.patch(
        f"/{vtag}/repos/projects/{project_uuid}/checkpoints/{checkpoint1.id}",
        json={
            "message": "updated message",
            "tag": "Version 1"
        },
    )
    data, _ = await assert_status(resp, web.HTTPOk)
    checkpoint1_updated = CheckpointApiModel.parse_obj(data)

    assert checkpoint1.id == checkpoint1_updated.id
    assert checkpoint1.checksum == checkpoint1_updated.checksum
    assert checkpoint1_updated.tags == ("Version 1", )
    assert checkpoint1_updated.message == "updated message"

    # GET view
    resp = await client.get(
        f"/{vtag}/repos/projects/{project_uuid}/checkpoints/HEAD/workbench/view"
    )
    data, _ = await assert_status(resp, web.HTTPOk)
    assert (data["workbench"] == project.dict(exclude_none=True,
                                              exclude_unset=True)["workbench"])

    # do some changes in project
    await do_update_user_project(project.uuid)

    # CREATE new checkpoint
    resp = await client.post(
        f"/{vtag}/repos/projects/{project_uuid}/checkpoints",
        json={
            "tag": "v2",
            "message": "new commit"
        },
    )
    data, _ = await assert_status(resp, web.HTTPCreated)
    checkpoint2 = CheckpointApiModel.parse_obj(data)
    assert checkpoint2.tags == ("v2", )

    # GET checkpoint with HEAD
    resp = await client.get(
        f"/{vtag}/repos/projects/{project_uuid}/checkpoints/HEAD")
    data, _ = await assert_status(resp, web.HTTPOk)
    assert CheckpointApiModel.parse_obj(data) == checkpoint2

    # CHECKOUT
    resp = await client.post(
        f"/{vtag}/repos/projects/{project_uuid}/checkpoints/{checkpoint1.id}:checkout"
    )
    data, _ = await assert_status(resp, web.HTTPOk)
    assert CheckpointApiModel.parse_obj(data) == checkpoint1_updated

    # GET checkpoint with HEAD
    resp = await client.get(
        f"/{vtag}/repos/projects/{project_uuid}/checkpoints/HEAD")
    data, _ = await assert_status(resp, web.HTTPOk)
    assert CheckpointApiModel.parse_obj(data) == checkpoint1_updated

    # get working copy
    resp = await client.get(f"/{vtag}/projects/{project_uuid}")
    data, _ = await assert_status(resp, web.HTTPOk)
    project_wc = Project.parse_obj(data)
    assert project_wc.uuid == UUID(project_uuid)
    assert project_wc != project
예제 #7
0
def test_project_minimal_model(minimal_project: Dict[str, Any]):
    project = Project.parse_obj(minimal_project)
    assert project

    assert project.thumbnail == None
예제 #8
0
    results = Page[ProjectIterationResultItem].parse_obj(body).data

    # GET project and MODIFY iterator values----------------------------------------------
    #  - Change iterations from 0:4 -> HEAD+1
    resp = await client.get(f"/v0/projects/{project_uuid}")
    assert resp.status == HTTPStatus.OK, await resp.text()
    body = await resp.json()

    # NOTE: updating a project fields can be daunting because
    # it combines nested field attributes with dicts and from the
    # json you cannot distinguish easily what-is-what automatically
    # Dict keys are usually some sort of identifier, typically a UUID or
    # and index but nothing prevents a dict from using any other type of key types
    #
    project = Project.parse_obj(body["data"])
    new_project = project.copy(
        update={
            # TODO: HACK to overcome export from None -> string
            # SOLUTION 1: thumbnail should not be required (check with team!)
            # SOLUTION 2: make thumbnail nullable
            "thumbnail": faker.image_url(),
        }
    )
    assert new_project.workbench is not None
    assert new_project.workbench
    node = new_project.workbench["fc9208d9-1a0a-430c-9951-9feaf1de3368"]
    assert node.inputs
    node.inputs["linspace_stop"] = 4

    resp = await client.put(