active user
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
+2
@@ -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,
|
||||
+1
@@ -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,
|
||||
+2
-6
@@ -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,
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
@@ -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):
|
||||
|
||||
@@ -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")
|
||||
|
||||
+8
-3
@@ -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
|
||||
@@ -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):
|
||||
|
||||
+5
-3
@@ -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
|
||||
@@ -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")
|
||||
|
||||
@@ -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):
|
||||
|
||||
+10
-2
@@ -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
|
||||
Reference in New Issue
Block a user