from re import search from typing import Dict, List, Optional from pydantic import BaseModel from gql import gql from speckle.api.resource import ResourceBase from speckle.api.models import Stream from speckle.logging.exceptions import GraphQLException NAME = "stream" METHODS = [ "list", "create", "get", "update", "delete", "search", ] class Resource(ResourceBase): """API Access class for streams""" def __init__(self, me, basepath, client) -> None: super().__init__( me=me, basepath=basepath, client=client, name=NAME, methods=METHODS ) self.schema = Stream def get(self, id: str, branch_limit: int = 10, commit_limit: int = 10) -> Stream: """Get the specified stream from the server Arguments: id {str} -- the stream id branch_limit {int} -- the maximum number of branches to return commit_limit {int} -- the maximum number of commits to return Returns: Stream -- the retrieved stream """ query = gql( """ query Stream($id: String!, $branch_limit: Int!, $commit_limit: Int!) { stream(id: $id) { id name description isPublic createdAt updatedAt collaborators { id name role avatar } branches(limit: $branch_limit) { totalCount cursor items { id name description commits(limit: $commit_limit) { totalCount cursor items { id referencedObject message authorName authorId createdAt } } } } } } """ ) params = {"id": id, "branch_limit": branch_limit, "commit_limit": commit_limit} return self.make_request(query=query, params=params, return_type="stream") def list(self, stream_limit: int = 10) -> List[Stream]: """Get a list of the user's streams Arguments: stream_limit {int} -- The maximum number of streams to return Returns: List[Stream] -- A list of Stream objects """ query = gql( """ query User($stream_limit: Int!) { user { id email name bio company avatar verified profiles role streams(limit: $stream_limit) { totalCount cursor items { id name description isPublic createdAt updatedAt collaborators { id name role } } } } } """ ) params = {"stream_limit": stream_limit} return self.make_request( query=query, params=params, return_type=["user", "streams", "items"] ) def create( self, name: str = "Anonymous Python Stream", description: str = "No description provided", is_public: bool = True, ) -> str: """Create a new stream Arguments: name {str} -- the name of the string description {str} -- a short description of the stream is_public {bool} -- whether or not the stream can be viewed by anyone with the id Returns: id {str} -- the id of the newly created stream """ query = gql( """ mutation StreamCreate($stream: StreamCreateInput!) { streamCreate(stream: $stream) } """ ) params = { "stream": {"name": name, "description": description, "isPublic": is_public} } return self.make_request( query=query, params=params, return_type="streamCreate", parse_response=False ) def update( self, id: str, name: str = None, description: str = None, is_public: bool = None ) -> bool: """Update an existing stream Arguments: id {str} -- the id of the stream to be updated name {str} -- the name of the string description {str} -- a short description of the stream is_public {bool} -- whether or not the stream can be viewed by anyone with the id Returns: bool -- whether the stream update was successful """ query = gql( """ mutation StreamUpdate($stream: StreamUpdateInput!) { streamUpdate(stream: $stream) } """ ) params = { "id": id, "name": name, "description": description, "isPublic": is_public, } # remove None values so graphql doesn't cry params = {"stream": {k: v for k, v in params.items() if v is not None}} return self.make_request( query=query, params=params, return_type="streamUpdate", parse_response=False ) def delete(self, id: str) -> bool: """Delete a stream given its id Arguments: id {str} -- the id of the stream to delete Returns: bool -- whether the deletion was successful """ query = gql( """ mutation StreamDelete($id: String!) { streamDelete(id: $id) } """ ) params = {"id": id} return self.make_request( query=query, params=params, return_type="streamDelete", parse_response=False ) def search( self, search_query: str, limit: int = 25, branch_limit: int = 10, commit_limit: int = 10, ): """Search for streams by name, description, or id Arguments: search_query {str} -- a string to search for limit {int} -- the maximum number of results to return branch_limit {int} -- the maximum number of branches to return commit_limit {int} -- the maximum number of commits to return Returns: List[Stream] -- a list of Streams that match the search query """ query = gql( """ query StreamSearch($search_query: String!,$limit: Int!, $branch_limit:Int!, $commit_limit:Int!) { streams(query: $search_query, limit: $limit) { items { id name description isPublic createdAt updatedAt collaborators { id name role avatar } branches(limit: $branch_limit) { totalCount cursor items { id name description commits(limit: $commit_limit) { totalCount cursor items { id referencedObject message authorName authorId createdAt } } } } } } } """ ) params = { "search_query": search_query, "limit": limit, "branch_limit": branch_limit, "commit_limit": commit_limit, } return self.make_request( query=query, params=params, return_type=["streams", "items"] ) def grant_permission(self, stream_id: str, user_id: str, role: str): """Grant permissions to a user on a given stream Arguments: stream_id {str} -- the id of the stream to grant permissions to user_id {str} -- the id of the user to grant permissions for role {str} -- the role to grant the user Returns: bool -- True if the operation was successful """ query = gql( """ mutation StreamGrantPermission($permission_params: StreamGrantPermissionInput !) { streamGrantPermission(permissionParams: $permission_params) } """ ) params = { "permission_params": { "streamId": stream_id, "userId": user_id, "role": role, } } return self.make_request( query=query, params=params, return_type="streamGrantPermission", parse_response=False, ) def revoke_permission(self, stream_id: str, user_id: str): """Revoke permissions from a user on a given stream Arguments: stream_id {str} -- the id of the stream to revoke permissions from user_id {str} -- the id of the user to revoke permissions from Returns: bool -- True if the operation was successful """ query = gql( """ mutation StreamRevokePermission($permission_params: StreamRevokePermissionInput !) { streamRevokePermission(permissionParams: $permission_params) } """ ) params = {"permission_params": {"streamId": stream_id, "userId": user_id}} return self.make_request( query=query, params=params, return_type="streamRevokePermission", parse_response=False, )