diff --git a/src/specklepy/api/client.py b/src/specklepy/api/client.py index bd169d8..aa76069 100644 --- a/src/specklepy/api/client.py +++ b/src/specklepy/api/client.py @@ -2,7 +2,6 @@ from deprecated import deprecated from specklepy.api.credentials import Account from specklepy.api.resources import ( - active_user, branch, commit, object, @@ -13,9 +12,12 @@ from specklepy.api.resources import ( user, ) from specklepy.core.api.client import SpeckleClient as CoreSpeckleClient -from specklepy.core.api.resources.model import ModelResource -from specklepy.core.api.resources.project import ProjectResource -from specklepy.core.api.resources.version import VersionResource + +# TODO: re-reference core.api resources +from specklepy.core.api.resources.active_user_resource import ActiveUserResource +from specklepy.core.api.resources.model_resource import ModelResource +from specklepy.core.api.resources.project_resource import ProjectResource +from specklepy.core.api.resources.version_resource import VersionResource from specklepy.logging import metrics @@ -83,7 +85,7 @@ class SpeckleClient(CoreSpeckleClient): client=self.httpclient, server_version=server_version, ) - self.active_user = active_user.Resource( + self.active_user = ActiveUserResource( account=self.account, basepath=self.url, client=self.httpclient, diff --git a/src/specklepy/api/resources/active_user.py b/src/specklepy/api/resources/active_user.py index 26016e6..aaf0261 100644 --- a/src/specklepy/api/resources/active_user.py +++ b/src/specklepy/api/resources/active_user.py @@ -2,7 +2,9 @@ from datetime import datetime from typing import List, Optional from specklepy.api.models import PendingStreamCollaborator, User -from specklepy.core.api.resources.active_user import Resource as CoreResource +from specklepy.core.api.resources.active_user_resource import ( + ActiveUserResource as CoreResource, +) from specklepy.logging import metrics diff --git a/src/specklepy/core/api/client.py b/src/specklepy/core/api/client.py index ed9c776..bc14fc5 100644 --- a/src/specklepy/core/api/client.py +++ b/src/specklepy/core/api/client.py @@ -11,7 +11,6 @@ from gql.transport.websockets import WebsocketsTransport from specklepy.core.api import resources from specklepy.core.api.credentials import Account, get_account_from_token from specklepy.core.api.resources import ( - active_user, branch, commit, object, @@ -21,6 +20,10 @@ from specklepy.core.api.resources import ( subscriptions, user, ) +from specklepy.core.api.resources.active_user_resource import ActiveUserResource +from specklepy.core.api.resources.model_resource import ModelResource +from specklepy.core.api.resources.project_resource import ProjectResource +from specklepy.core.api.resources.version_resource import VersionResource from specklepy.logging import metrics from specklepy.logging.exceptions import SpeckleException, SpeckleWarning @@ -200,24 +203,45 @@ class SpeckleClient: self.server = server.Resource( account=self.account, basepath=self.url, client=self.httpclient ) + server_version = None try: server_version = self.server.version() except Exception: pass - self.user = user.Resource( - account=self.account, - basepath=self.url, - client=self.httpclient, - server_version=server_version, - ) + self.other_user = other_user.Resource( account=self.account, basepath=self.url, client=self.httpclient, server_version=server_version, ) - self.active_user = active_user.Resource( + self.active_user = ActiveUserResource( + account=self.account, + basepath=self.url, + client=self.httpclient, + server_version=server_version, + ) + self.project = ProjectResource( + account=self.account, + basepath=self.url, + client=self.httpclient, + server_version=server_version, + ) + self.model = ModelResource( + account=self.account, + basepath=self.url, + client=self.httpclient, + server_version=server_version, + ) + self.version = VersionResource( + account=self.account, + basepath=self.url, + client=self.httpclient, + server_version=server_version, + ) + # Deprecated Resources + self.user = user.Resource( account=self.account, basepath=self.url, client=self.httpclient, diff --git a/src/specklepy/core/api/credentials.py b/src/specklepy/core/api/credentials.py index 46531b7..9999ce2 100644 --- a/src/specklepy/core/api/credentials.py +++ b/src/specklepy/core/api/credentials.py @@ -12,10 +12,11 @@ from specklepy.transports.sqlite import SQLiteTransport class UserInfo(BaseModel): + id: Optional[str] = None name: Optional[str] = None email: Optional[str] = None company: Optional[str] = None - id: Optional[str] = None + avatar: Optional[str] = None class Account(BaseModel): diff --git a/src/specklepy/core/api/inputs/user_inputs.py b/src/specklepy/core/api/inputs/user_inputs.py new file mode 100644 index 0000000..de6c112 --- /dev/null +++ b/src/specklepy/core/api/inputs/user_inputs.py @@ -0,0 +1,9 @@ +from typing import Optional +from pydantic import BaseModel + + +class UserUpdateInput(BaseModel): + avatar: Optional[str] = None + bio: Optional[str] = None + company: Optional[str] = None + name: Optional[str] = None diff --git a/src/specklepy/core/api/resources/active_user.py b/src/specklepy/core/api/resources/active_user.py index aeb190b..9164706 100644 --- a/src/specklepy/core/api/resources/active_user.py +++ b/src/specklepy/core/api/resources/active_user.py @@ -1,279 +1,14 @@ -from datetime import datetime, timezone -from typing import List, Optional +from deprecated import deprecated +from specklepy.core.api.models import FE1_DEPRECATION_VERSION +from specklepy.core.api.resources.active_user_resource import ActiveUserResource -from gql import gql -from specklepy.core.api.models import ( - ActivityCollection, - PendingStreamCollaborator, - User, +@deprecated( + reason="Class renamed to ActiveUserResource", version=FE1_DEPRECATION_VERSION ) -from specklepy.core.api.resource import ResourceBase -from specklepy.logging.exceptions import SpeckleException +class Resource(ActiveUserResource): + """ + Class renamed to ActiveUserResource + """ -NAME = "active_user" - - -class Resource(ResourceBase): - """API Access class for users""" - - def __init__(self, account, basepath, client, server_version) -> None: - super().__init__( - account=account, - basepath=basepath, - client=client, - name=NAME, - server_version=server_version, - ) - self.schema = User - - def get(self) -> User: - """Gets the profile of a user. If no id argument is provided, - will return the current authenticated user's profile - (as extracted from the authorization header). - - Arguments: - id {str} -- the user id - - Returns: - User -- the retrieved user - """ - query = gql( - """ - query User { - activeUser { - id - email - name - bio - company - avatar - verified - profiles - role - } - } - """ - ) - - params = {} - - return self.make_request(query=query, params=params, return_type="activeUser") - - def update( - self, - name: Optional[str] = None, - company: Optional[str] = None, - bio: Optional[str] = None, - avatar: Optional[str] = None, - ) -> bool: - """Updates your user profile. All arguments are optional. - - Arguments: - name {str} -- your name - company {str} -- the company you may or may not work for - bio {str} -- tell us about yourself - avatar {str} -- a nice photo of yourself - - Returns @deprecated(version=DEPRECATION_VERSION, reason=DEPRECATION_TEXT): - bool -- True if your profile was updated successfully - """ - query = gql( - """ - mutation UserUpdate($user: UserUpdateInput!) { - userUpdate(user: $user) - } - """ - ) - params = {"name": name, "company": company, "bio": bio, "avatar": avatar} - - params = {"user": {k: v for k, v in params.items() if v is not None}} - - if not params["user"]: - return SpeckleException( - message=( - "You must provide at least one field to update your user profile" - ) - ) - - return self.make_request( - query=query, params=params, return_type="userUpdate", parse_response=False - ) - - def activity( - self, - limit: int = 20, - action_type: Optional[str] = None, - before: Optional[datetime] = None, - after: Optional[datetime] = None, - cursor: Optional[datetime] = None, - ) -> ActivityCollection: - """ - Get the activity from a given stream in an Activity collection. - Step into the activity `items` for the list of activity. - If no id argument is provided, will return the current authenticated user's - activity (as extracted from the authorization header). - - Note: all timestamps arguments should be `datetime` of any tz as they will be - converted to UTC ISO format strings - - user_id {str} -- the id of the user to get the activity from - action_type {str} -- filter results to a single action type - (eg: `commit_create` or `commit_receive`) - limit {int} -- max number of Activity items to return - before {datetime} -- latest cutoff for activity - (ie: return all activity _before_ this time) - after {datetime} -- oldest cutoff for activity - (ie: return all activity _after_ this time) - cursor {datetime} -- timestamp cursor for pagination - """ - - query = gql( - """ - query UserActivity( - $action_type: String, - $before:DateTime, - $after: DateTime, - $cursor: DateTime, - $limit: Int - ){ - activeUser { - activity( - actionType: $action_type, - before: $before, - after: $after, - cursor: $cursor, - limit: $limit - ) { - totalCount - cursor - items { - actionType - info - userId - streamId - resourceId - resourceType - message - time - } - } - } - } - """ - ) - - params = { - "limit": limit, - "action_type": action_type, - "before": before.astimezone(timezone.utc).isoformat() if before else before, - "after": after.astimezone(timezone.utc).isoformat() if after else after, - "cursor": cursor.astimezone(timezone.utc).isoformat() if cursor else cursor, - } - - return self.make_request( - query=query, - params=params, - return_type=["activeUser", "activity"], - schema=ActivityCollection, - ) - - def get_all_pending_invites(self) -> List[PendingStreamCollaborator]: - """Get all of the active user's pending stream invites - - Requires Speckle Server version >= 2.6.4 - - Returns: - List[PendingStreamCollaborator] - -- a list of pending invites for the current user - """ - self._check_invites_supported() - - query = gql( - """ - query StreamInvites { - streamInvites{ - id - token - inviteId - streamId - streamName - projectId - projectName - title - role - invitedBy { - id - name - bio - company - avatar - verified - role - } - } - } - """ - ) - - return self.make_request( - query=query, - return_type="streamInvites", - schema=PendingStreamCollaborator, - ) - - def get_pending_invite( - self, stream_id: str, token: Optional[str] = None - ) -> Optional[PendingStreamCollaborator]: - """Get a particular pending invite for the active user on a given stream. - If no invite_id is provided, any valid invite will be returned. - - Requires Speckle Server version >= 2.6.4 - - Arguments: - stream_id {str} -- the id of the stream to look for invites on - token {str} -- the token of the invite to look for (optional) - - Returns: - PendingStreamCollaborator - -- the invite for the given stream (or None if it isn't found) - """ - self._check_invites_supported() - - query = gql( - """ - query StreamInvite($streamId: String!, $token: String) { - streamInvite(streamId: $streamId, token: $token) { - id - token - inviteId - streamId - streamName - projectId - projectName - title - role - invitedBy { - id - name - bio - company - avatar - verified - role - } - } - } - """ - ) - - params = {"streamId": stream_id} - if token: - params["token"] = token - - return self.make_request( - query=query, - params=params, - return_type="streamInvite", - schema=PendingStreamCollaborator, - ) + pass diff --git a/src/specklepy/core/api/resources/active_user_resource.py b/src/specklepy/core/api/resources/active_user_resource.py new file mode 100644 index 0000000..d5d784d --- /dev/null +++ b/src/specklepy/core/api/resources/active_user_resource.py @@ -0,0 +1,373 @@ +from datetime import datetime, timezone +from typing import List, Optional + +from deprecated import deprecated +from gql import gql + +from specklepy.core.api.inputs.project_inputs import UserProjectsFilter +from specklepy.core.api.inputs.user_inputs import UserUpdateInput +from specklepy.core.api.models import ( + FE1_DEPRECATION_REASON, + FE1_DEPRECATION_VERSION, + ActivityCollection, + PendingStreamCollaborator, + User, +) +from specklepy.core.api.new_models import Project +from specklepy.core.api.resource import ResourceBase +from specklepy.core.api.responses import DataResponse, ResourceCollection +from specklepy.logging.exceptions import GraphQLException + +NAME = "active_user" + + +class ActiveUserResource(ResourceBase): + """API Access class for users""" + + def __init__(self, account, basepath, client, server_version) -> None: + super().__init__( + account=account, + basepath=basepath, + client=client, + name=NAME, + server_version=server_version, + ) + self.schema = User + + def get(self) -> Optional[User]: + """Gets the currently active user profile (as extracted from the authorization header) + + Returns: + User -- the requested user, or none if no authentication token is provided to the Client + """ + QUERY = gql( + """ + query User { + data:activeUser { + id + email + name + bio + company + avatar + verified + role + } + } + """ + ) + + variables = {} + + return self.make_request_and_parse_response( + DataResponse[Optional[User]], QUERY, variables + ).data + + # todo: breaking change, can we make this not? + def update(self, input: UserUpdateInput) -> User: + QUERY = gql( + """ + mutation ActiveUserMutations($input: UserUpdateInput!) { + data:activeUserMutations { + data:update(user: $input) { + id + email + name + bio + company + avatar + verified + role + } + } + } + """ + ) + + variables = {"input": input.model_dump(warnings="error")} + + return self.make_request_and_parse_response( + DataResponse[DataResponse[User]], QUERY, variables + ).data.data + + def get_projects( + self, + *, + limit: int = 25, + cursor: Optional[str] = None, + filter: Optional[UserProjectsFilter] = None, + ) -> ResourceCollection[Project]: + QUERY = gql( + """ + query User($limit : Int!, $cursor: String, $filter: UserProjectsFilter) { + data:activeUser { + data:projects(limit: $limit, cursor: $cursor, filter: $filter) { + totalCount + items { + id + name + description + visibility + allowPublicComments + role + createdAt + updatedAt + sourceApps + workspaceId + } + } + } + } + """ + ) + + variables = { + "limit": limit, + "cursor": cursor, + "filter": filter.model_dump(warnings="error") if filter else None, + } + + response = self.make_request_and_parse_response( + DataResponse[Optional[DataResponse[ResourceCollection[Project]]]], + QUERY, + variables, + ) + + if response.data is None: + raise GraphQLException( + "GraphQL response indicated that the ActiveUser could not be found" + ) + + return response.data.data + + def get_project_invites(self) -> List[PendingStreamCollaborator]: + QUERY = gql( + """ + query ProjectInvites { + data:activeUser { + data:projectInvites { + id + inviteId + invitedBy { + avatar + bio + company + id + name + role + verified + } + projectId + projectName + role + title + token + user { + id, + name, + bio, + company, + verified, + role, + } + } + } + } + """ + ) + + variables = {} + + response = self.make_request_and_parse_response( + DataResponse[Optional[DataResponse[List[PendingStreamCollaborator]]]], + QUERY, + variables, + ) + + if response.data is None: + raise GraphQLException( + "GraphQL response indicated that the ActiveUser could not be found" + ) + + return response.data.data + + @deprecated(reason=FE1_DEPRECATION_REASON, version=FE1_DEPRECATION_VERSION) + def activity( + self, + limit: int = 20, + action_type: Optional[str] = None, + before: Optional[datetime] = None, + after: Optional[datetime] = None, + cursor: Optional[datetime] = None, + ) -> ActivityCollection: + """ + Get the activity from a given stream in an Activity collection. + Step into the activity `items` for the list of activity. + If no id argument is provided, will return the current authenticated user's + activity (as extracted from the authorization header). + + Note: all timestamps arguments should be `datetime` of any tz as they will be + converted to UTC ISO format strings + + user_id {str} -- the id of the user to get the activity from + action_type {str} -- filter results to a single action type + (eg: `commit_create` or `commit_receive`) + limit {int} -- max number of Activity items to return + before {datetime} -- latest cutoff for activity + (ie: return all activity _before_ this time) + after {datetime} -- oldest cutoff for activity + (ie: return all activity _after_ this time) + cursor {datetime} -- timestamp cursor for pagination + """ + + query = gql( + """ + query UserActivity( + $action_type: String, + $before:DateTime, + $after: DateTime, + $cursor: DateTime, + $limit: Int + ){ + activeUser { + activity( + actionType: $action_type, + before: $before, + after: $after, + cursor: $cursor, + limit: $limit + ) { + totalCount + cursor + items { + actionType + info + userId + streamId + resourceId + resourceType + message + time + } + } + } + } + """ + ) + + params = { + "limit": limit, + "action_type": action_type, + "before": before.astimezone(timezone.utc).isoformat() if before else before, + "after": after.astimezone(timezone.utc).isoformat() if after else after, + "cursor": cursor.astimezone(timezone.utc).isoformat() if cursor else cursor, + } + + return self.make_request( + query=query, + params=params, + return_type=["activeUser", "activity"], + schema=ActivityCollection, + ) + + @deprecated(reason=FE1_DEPRECATION_REASON, version=FE1_DEPRECATION_VERSION) + def get_all_pending_invites(self) -> List[PendingStreamCollaborator]: + """Get all of the active user's pending stream invites + + Requires Speckle Server version >= 2.6.4 + + Returns: + List[PendingStreamCollaborator] + -- a list of pending invites for the current user + """ + self._check_invites_supported() + + query = gql( + """ + query StreamInvites { + streamInvites{ + id + token + inviteId + streamId + streamName + projectId + projectName + title + role + invitedBy { + id + name + bio + company + avatar + verified + role + } + } + } + """ + ) + + return self.make_request( + query=query, + return_type="streamInvites", + schema=PendingStreamCollaborator, + ) + + @deprecated(reason=FE1_DEPRECATION_REASON, version=FE1_DEPRECATION_VERSION) + def get_pending_invite( + self, stream_id: str, token: Optional[str] = None + ) -> Optional[PendingStreamCollaborator]: + """Get a particular pending invite for the active user on a given stream. + If no invite_id is provided, any valid invite will be returned. + + Requires Speckle Server version >= 2.6.4 + + Arguments: + stream_id {str} -- the id of the stream to look for invites on + token {str} -- the token of the invite to look for (optional) + + Returns: + PendingStreamCollaborator + -- the invite for the given stream (or None if it isn't found) + """ + self._check_invites_supported() + + query = gql( + """ + query StreamInvite($streamId: String!, $token: String) { + streamInvite(streamId: $streamId, token: $token) { + id + token + inviteId + streamId + streamName + projectId + projectName + title + role + invitedBy { + id + name + bio + company + avatar + verified + role + } + } + } + """ + ) + + params = {"streamId": stream_id} + if token: + params["token"] = token + + return self.make_request( + query=query, + params=params, + return_type="streamInvite", + schema=PendingStreamCollaborator, + ) diff --git a/src/specklepy/core/api/resources/model.py b/src/specklepy/core/api/resources/model_resource.py similarity index 99% rename from src/specklepy/core/api/resources/model.py rename to src/specklepy/core/api/resources/model_resource.py index 7f2c5e5..279776f 100644 --- a/src/specklepy/core/api/resources/model.py +++ b/src/specklepy/core/api/resources/model_resource.py @@ -66,6 +66,7 @@ class ModelResource(ResourceBase): self, model_id: str, project_id: str, + *, versions_limit: int = 25, versions_cursor: Optional[str] = None, versions_filter: Optional[ModelVersionsFilter] = None, @@ -135,6 +136,7 @@ class ModelResource(ResourceBase): def get_models( self, project_id: str, + *, models_limit: int = 25, models_cursor: Optional[str] = None, models_filter: Optional[ProjectModelsFilter] = None, diff --git a/src/specklepy/core/api/resources/project.py b/src/specklepy/core/api/resources/project_resource.py similarity index 99% rename from src/specklepy/core/api/resources/project.py rename to src/specklepy/core/api/resources/project_resource.py index 194fbfc..cdd81bb 100644 --- a/src/specklepy/core/api/resources/project.py +++ b/src/specklepy/core/api/resources/project_resource.py @@ -56,6 +56,7 @@ class ProjectResource(ResourceBase): def get_with_models( self, project_id: str, + *, models_limit: int = 25, models_cursor: Optional[str] = None, models_filter: Optional[ProjectModelsFilter] = None, diff --git a/src/specklepy/core/api/resources/version.py b/src/specklepy/core/api/resources/version_resource.py similarity index 96% rename from src/specklepy/core/api/resources/version.py rename to src/specklepy/core/api/resources/version_resource.py index d8ae6b6..e98d03b 100644 --- a/src/specklepy/core/api/resources/version.py +++ b/src/specklepy/core/api/resources/version_resource.py @@ -3,12 +3,8 @@ from typing import Optional from gql import gql from specklepy.core.api.inputs.model_inputs import ( - CreateModelInput, - DeleteModelInput, ModelVersionsFilter, - UpdateModelInput, ) -from specklepy.core.api.inputs.project_inputs import ProjectModelsFilter from specklepy.core.api.inputs.version_inputs import ( CreateVersionInput, DeleteVersionsInput, @@ -16,8 +12,7 @@ from specklepy.core.api.inputs.version_inputs import ( MoveVersionsInput, UpdateVersionInput, ) -from specklepy.core.api.models import Project -from specklepy.core.api.new_models import Model, ModelWithVersions, Version +from specklepy.core.api.new_models import Version from specklepy.core.api.resource import ResourceBase from specklepy.core.api.responses import DataResponse, ResourceCollection @@ -72,6 +67,7 @@ class VersionResource(ResourceBase): self, model_id: str, project_id: str, + *, limit: int = 25, cursor: Optional[str] = None, filter: Optional[ModelVersionsFilter] = None, diff --git a/tests/integration/client/test_active_user.py b/tests/integration/client/test_active_user.py index 755a8cb..7999843 100644 --- a/tests/integration/client/test_active_user.py +++ b/tests/integration/client/test_active_user.py @@ -1,10 +1,13 @@ +from deprecated import deprecated import pytest from specklepy.api.client import SpeckleClient from specklepy.api.models import Activity, ActivityCollection, User -from specklepy.logging.exceptions import SpeckleException +from specklepy.core.api.inputs.user_inputs import UserUpdateInput +from specklepy.logging.exceptions import GraphQLException +@deprecated @pytest.mark.run(order=2) class TestUser: def test_user_get_self(self, client: SpeckleClient, user_dict): @@ -19,15 +22,14 @@ class TestUser: def test_user_update(self, client: SpeckleClient): bio = "i am a ghost in the machine" - failed_update = client.active_user.update() - assert isinstance(failed_update, SpeckleException) + with pytest.raises(GraphQLException): + client.active_user.update(UserUpdateInput()) - updated = client.active_user.update(bio=bio) + updated = client.active_user.update(UserUpdateInput(bio=bio)) - me = client.active_user.get() - - assert updated is True - assert me.bio == bio + assert isinstance(updated, User) + assert isinstance(updated, User) + assert updated.bio == bio def test_user_activity(self, client: SpeckleClient, second_user_dict): my_activity = client.active_user.activity(limit=10) diff --git a/tests/integration/client/test_active_user_resource.py b/tests/integration/client/test_active_user_resource.py new file mode 100644 index 0000000..84b15d8 --- /dev/null +++ b/tests/integration/client/test_active_user_resource.py @@ -0,0 +1,44 @@ +import pytest +from specklepy.core.api.client import SpeckleClient +from specklepy.core.api.inputs.user_inputs import UserUpdateInput +from specklepy.core.api.inputs.project_inputs import ProjectCreateInput +from specklepy.core.api.models import User +from specklepy.core.api.responses import ResourceCollection + + +@pytest.mark.run() +class TestActiveUserResource: + def test_active_user_get(self, client: SpeckleClient): + res = client.active_user.get() + + assert isinstance(res, User) + + def test_active_user_update(self, client: SpeckleClient): + NEW_NAME = "Ron" + NEW_BIO = "Now I have a bio, isn't that nice!" + NEW_COMPANY = "Limited Cooperation Organization Inc" + + input_data = UserUpdateInput(name=NEW_NAME, bio=NEW_BIO, company=NEW_COMPANY) + res = client.active_user.update(input_data) + + assert isinstance(res, User) + assert res.name == NEW_NAME + assert res.bio == NEW_BIO + assert res.company == NEW_COMPANY + + def test_active_user_get_projects(self, client: SpeckleClient): + existing = client.active_user.get_projects() + + p1 = client.project.create( + ProjectCreateInput(name="Project 1", description=None, visibility=None) + ) + p2 = client.project.create( + ProjectCreateInput(name="Project 2", description=None, visibility=None) + ) + + res = client.active_user.get_projects() + + assert isinstance(res, ResourceCollection) + assert len(res.items) == len(existing.items) + 2 + assert any(project.id == p1.id for project in res.items) + assert any(project.id == p2.id for project in res.items) diff --git a/tests/integration/client/test_branch.py b/tests/integration/client/test_branch.py index 27bf8ba..f067c5c 100644 --- a/tests/integration/client/test_branch.py +++ b/tests/integration/client/test_branch.py @@ -1,3 +1,4 @@ +from deprecated import deprecated import pytest from specklepy.api import operations @@ -5,6 +6,7 @@ from specklepy.api.models import Branch, Commit, Stream from specklepy.transports.server import ServerTransport +@deprecated class TestBranch: @pytest.fixture(scope="module") def branch(self): diff --git a/tests/integration/client/test_commit.py b/tests/integration/client/test_commit.py index 9ce3c81..f609f09 100644 --- a/tests/integration/client/test_commit.py +++ b/tests/integration/client/test_commit.py @@ -1,3 +1,4 @@ +from deprecated import deprecated import pytest from specklepy.api import operations @@ -5,6 +6,7 @@ from specklepy.api.models import Commit, Stream from specklepy.transports.server.server import ServerTransport +@deprecated @pytest.mark.run(order=6) class TestCommit: @pytest.fixture(scope="module") diff --git a/tests/integration/client/test_model.py b/tests/integration/client/test_model_resource.py similarity index 90% rename from tests/integration/client/test_model.py rename to tests/integration/client/test_model_resource.py index 2e4d7e6..908e910 100644 --- a/tests/integration/client/test_model.py +++ b/tests/integration/client/test_model_resource.py @@ -8,11 +8,13 @@ from specklepy.core.api.inputs.model_inputs import ( ) from specklepy.core.api.inputs.project_inputs import ProjectCreateInput from specklepy.core.api.models import Model, Project +from specklepy.core.api.new_models import ProjectWithModels +from specklepy.core.api.responses import ResourceCollection from specklepy.logging.exceptions import GraphQLException @pytest.mark.run() -class TestModel: +class TestModelResource: @pytest.fixture() def test_project(self, client: SpeckleClient) -> Project: project = client.project.create( @@ -44,8 +46,7 @@ class TestModel: ) result = client.model.create(input_data) - assert result is not None - assert result.id is not None + assert isinstance(result, Model) assert result.name.lower() == name.lower() assert result.description == description @@ -54,6 +55,7 @@ class TestModel: ): result = client.model.get(test_model.id, test_project.id) + assert isinstance(result, Model) assert result.id == test_model.id assert result.name == test_model.name assert result.description == test_model.description @@ -65,6 +67,7 @@ class TestModel: ): result = client.model.get_models(test_project.id) + assert isinstance(result, ResourceCollection) assert len(result.items) == 1 assert result.totalCount == 1 assert result.items[0].id == test_model.id @@ -74,6 +77,7 @@ class TestModel: ): result = client.project.get_with_models(test_project.id) + assert isinstance(result, ProjectWithModels) assert result.id == test_project.id assert len(result.models.items) == 1 assert result.models.totalCount == 1 @@ -94,6 +98,7 @@ class TestModel: updated_model = client.model.update(update_data) + assert isinstance(updated_model, Model) assert updated_model.id == test_model.id assert updated_model.name.lower() == new_name.lower() assert updated_model.description == new_description diff --git a/tests/integration/client/test_objects.py b/tests/integration/client/test_objects.py index f921ee6..d753e3f 100644 --- a/tests/integration/client/test_objects.py +++ b/tests/integration/client/test_objects.py @@ -1,3 +1,4 @@ +from deprecated import deprecated import pytest from specklepy.api.models import Stream @@ -7,6 +8,7 @@ from specklepy.serialization.base_object_serializer import BaseObjectSerializer from specklepy.transports.sqlite import SQLiteTransport +@deprecated class TestObject: @pytest.fixture(scope="module") def stream(self, client): diff --git a/tests/integration/client/test_project.py b/tests/integration/client/test_project_resource.py similarity index 94% rename from tests/integration/client/test_project.py rename to tests/integration/client/test_project_resource.py index 07bb6a2..f1c805d 100644 --- a/tests/integration/client/test_project.py +++ b/tests/integration/client/test_project_resource.py @@ -11,8 +11,8 @@ from specklepy.logging.exceptions import GraphQLException @pytest.mark.run() -class TestProject: - @pytest.fixture(scope="session") +class TestProjectResource: + @pytest.fixture() def test_project(self, client: SpeckleClient) -> Project: project = client.project.create( ProjectCreateInput( @@ -44,7 +44,7 @@ class TestProject: ) result = client.project.create(input_data) - assert result is not None + assert isinstance(result, Project) assert result.id is not None assert result.name == name assert result.description == (description or "") @@ -53,6 +53,7 @@ class TestProject: def test_project_get(self, client: SpeckleClient, test_project: Project): result = client.project.get(test_project.id) + assert isinstance(result, Project) assert result.id == test_project.id assert result.name == test_project.name assert result.description == test_project.description @@ -73,6 +74,7 @@ class TestProject: updated_project = client.project.update(update_data) + assert isinstance(updated_project, Project) assert updated_project.id == test_project.id assert updated_project.name == new_name assert updated_project.description == new_description diff --git a/tests/integration/client/test_stream.py b/tests/integration/client/test_stream.py index 84ce5f7..7dc10b9 100644 --- a/tests/integration/client/test_stream.py +++ b/tests/integration/client/test_stream.py @@ -1,3 +1,4 @@ +from deprecated import deprecated import pytest from specklepy.api.client import SpeckleClient @@ -11,6 +12,7 @@ from specklepy.api.models import ( from specklepy.logging.exceptions import GraphQLException, SpeckleException +@deprecated @pytest.mark.run(order=3) class TestStream: @pytest.fixture(scope="session") diff --git a/tests/integration/client/test_user.py b/tests/integration/client/test_user.py index 5885985..8547b5c 100644 --- a/tests/integration/client/test_user.py +++ b/tests/integration/client/test_user.py @@ -1,3 +1,4 @@ +from deprecated import deprecated import pytest from specklepy.api.client import SpeckleClient @@ -5,6 +6,7 @@ from specklepy.api.models import Activity, ActivityCollection, User from specklepy.logging.exceptions import SpeckleException +@deprecated @pytest.mark.run(order=1) class TestUser: def test_user_get_self(self, client: SpeckleClient, user_dict): diff --git a/tests/integration/client/test_version.py b/tests/integration/client/test_version_resource.py similarity index 91% rename from tests/integration/client/test_version.py rename to tests/integration/client/test_version_resource.py index a3b91cf..f4c7859 100644 --- a/tests/integration/client/test_version.py +++ b/tests/integration/client/test_version_resource.py @@ -12,13 +12,15 @@ from specklepy.core.api.inputs.version_inputs import ( UpdateVersionInput, ) from specklepy.core.api.models import Model, Project, Version +from specklepy.core.api.new_models import ModelWithVersions +from specklepy.core.api.responses import ResourceCollection from specklepy.logging.exceptions import GraphQLException from specklepy.objects.base import Base from specklepy.transports.server.server import ServerTransport -@pytest.mark.run(order=4) -class TestVersion: +@pytest.mark.run() +class TestVersionResource: @pytest.fixture def test_project(self, client: SpeckleClient) -> Project: project = client.project.create( @@ -63,6 +65,7 @@ class TestVersion: ): result = client.version.get(test_version.id, test_project.id) + assert isinstance(result, Version) assert result.id == test_version.id assert result.message == test_version.message @@ -75,6 +78,7 @@ class TestVersion: ): result = client.version.get_versions(test_model_1.id, test_project.id) + assert isinstance(result, ResourceCollection) assert len(result.items) == 1 assert result.totalCount == 1 assert result.items[0].id == test_version.id @@ -100,6 +104,7 @@ class TestVersion: ): result = client.model.get_with_versions(test_model_1.id, test_project.id) + assert isinstance(result, ModelWithVersions) assert result.id == test_model_1.id assert len(result.versions.items) == 1 assert result.versions.totalCount == 1 @@ -110,6 +115,7 @@ class TestVersion: input_data = UpdateVersionInput(versionId=test_version.id, message=new_message) updated_version = client.version.update(input_data) + assert isinstance(updated_version, Version) assert updated_version.id == test_version.id assert updated_version.message == new_message assert updated_version.previewUrl == test_version.previewUrl @@ -126,9 +132,11 @@ class TestVersion: ) moved_model_id = client.version.move_to_model(input_data) + assert isinstance(moved_model_id, str) assert moved_model_id == test_model_2.id moved_version = client.version.get(test_version.id, test_project.id) + assert isinstance(moved_version, Version) assert moved_version.id == test_version.id assert moved_version.message == test_version.message assert moved_version.previewUrl == test_version.previewUrl