Skip to content

Commit

Permalink
Merge pull request #384 from specklesystems/jedd/cxpla-167-update-pyt…
Browse files Browse the repository at this point in the history
…hon-automate-sdk-to-use-fe2-api

Update Automate to use FE2 API
  • Loading branch information
gjedlicska authored Feb 18, 2025
2 parents 1b53410 + 37e9c23 commit da6e2d9
Show file tree
Hide file tree
Showing 28 changed files with 275 additions and 237 deletions.
98 changes: 51 additions & 47 deletions src/speckle_automate/automation_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import time
from dataclasses import dataclass, field
from pathlib import Path
from typing import Any, Dict, List, Optional, Tuple, Union
from typing import Any, Dict, List, Optional, Union

import httpx
from gql import gql
Expand All @@ -20,7 +20,9 @@
)
from specklepy.api import operations
from specklepy.api.client import SpeckleClient
from specklepy.core.api.models import Branch
from specklepy.core.api.inputs.model_inputs import CreateModelInput
from specklepy.core.api.inputs.version_inputs import CreateVersionInput
from specklepy.core.api.models.current import Model, Version
from specklepy.logging.exceptions import SpeckleException
from specklepy.objects.base import Base
from specklepy.transports.memory import MemoryTransport
Expand Down Expand Up @@ -101,88 +103,90 @@ def receive_version(self) -> Base:
# TODO: this is a quick hack to keep implementation consistency.
# Move to proper receive many versions
version_id = self.automation_run_data.triggers[0].payload.version_id
commit = self.speckle_client.commit.get(
self.automation_run_data.project_id, version_id
)
if not commit or not commit.referencedObject:
try:
version = self.speckle_client.version.get(
version_id, self.automation_run_data.project_id
)
except SpeckleException as err:
raise ValueError(
f"""\
Could not receive specified version.
{"The commit has no referencedObject." if not commit.referencedObject else ""}
Is your environment configured correctly?
project_id: {self.automation_run_data.project_id}
model_id: {self.automation_run_data.triggers[0].payload.model_id}
version_id: {self.automation_run_data.triggers[0].payload.version_id}
"""
)
) from err

base = operations.receive(
commit.referencedObject, self._server_transport, self._memory_transport
version.referenced_object, self._server_transport, self._memory_transport
)
print(
f"It took {self.elapsed():.2f} seconds to receive",
f" the speckle version {version_id}",
)
return base

def create_new_model_in_project(
self, model_name: str, model_description: Optional[str] = None
) -> Model:
input = CreateModelInput(
name=model_name,
description=model_description,
project_id=self.automation_run_data.project_id,
)

return self.speckle_client.model.create(input)

def get_model(self, model_id: str) -> Model:
"""
Args:
model_id (str): The id of the model to get
"""
return self.speckle_client.model.get(
model_id, self.automation_run_data.project_id
)

def create_new_version_in_project(
self, root_object: Base, model_name: str, version_message: str = ""
) -> Tuple[str, str]:
self, root_object: Base, model_id: str, version_message: str = ""
) -> Version:
"""Save a base model to a new version on the project.
Args:
root_object (Base): The Speckle base object for the new version.
model_id (str): For now please use a `branchName`!
model_id (str): Id of model to create the new version on.
version_message (str): The message for the new version.
"""

branch = self.speckle_client.branch.get(
self.automation_run_data.project_id, model_name, 1
)
if isinstance(branch, Branch):
if not branch.id:
raise ValueError("Cannot use the branch without its id")
matching_trigger = [
t
for t in self.automation_run_data.triggers
if t.payload.model_id == branch.id
]
if matching_trigger:
raise ValueError(
f"The target model: {model_name} cannot match the model"
f" that triggered this automation:"
f" {matching_trigger[0].payload.model_id}"
)
model_id = branch.id

else:
# we just check if it exists
branch_create = self.speckle_client.branch.create(
self.automation_run_data.project_id,
model_name,
matching_trigger = [
t
for t in self.automation_run_data.triggers
if t.payload.model_id == model_id
]
if matching_trigger:
raise ValueError(
f"The target model: {model_id} cannot match the model"
f" that triggered this automation:"
f" {matching_trigger[0].payload.model_id}"
)
if isinstance(branch_create, Exception):
raise branch_create
model_id = branch_create

root_object_id = operations.send(
root_object,
[self._server_transport, self._memory_transport],
use_default_cache=False,
)

version_id = self.speckle_client.commit.create(
stream_id=self.automation_run_data.project_id,
create_version_input = CreateVersionInput(
object_id=root_object_id,
branch_name=model_name,
model_id=model_id,
project_id=self.automation_run_data.project_id,
message=version_message,
source_application="SpeckleAutomate",
)
version = self.speckle_client.version.create(create_version_input)

if isinstance(version_id, SpeckleException):
raise version_id

self._automation_result.result_versions.append(version_id)
return model_id, version_id
self._automation_result.result_versions.append(version.id)
return version

@property
def context_view(self) -> Optional[str]:
Expand Down
2 changes: 1 addition & 1 deletion src/specklepy/api/resources/current/version_resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def get_versions(
model_id, project_id, limit=limit, cursor=cursor, filter=filter
)

def create(self, input: CreateVersionInput) -> str:
def create(self, input: CreateVersionInput) -> Version:
metrics.track(metrics.SDK, self.account, {"name": "Version Create"})
return super().create(input)

Expand Down
2 changes: 1 addition & 1 deletion src/specklepy/core/api/credentials.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ def get_accounts_for_server(host: str) -> List[Account]:

for acc in all_accounts:
moved_from = (
acc.serverInfo.migration.movedFrom if acc.serverInfo.migration else None
acc.serverInfo.migration.moved_from if acc.serverInfo.migration else None
)

if moved_from and host == urlparse(moved_from).netloc:
Expand Down
20 changes: 10 additions & 10 deletions src/specklepy/core/api/inputs/model_inputs.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
from typing import Optional, Sequence

from pydantic import BaseModel
from specklepy.core.api.models.graphql_base_model import GraphQLBaseModel


class CreateModelInput(BaseModel):
class CreateModelInput(GraphQLBaseModel):
name: str
description: Optional[str] = None
projectId: str
project_id: str


class DeleteModelInput(BaseModel):
class DeleteModelInput(GraphQLBaseModel):
id: str
projectId: str
project_id: str


class UpdateModelInput(BaseModel):
class UpdateModelInput(GraphQLBaseModel):
id: str
name: Optional[str] = None
description: Optional[str] = None
projectId: str
project_id: str


class ModelVersionsFilter(BaseModel):
priorityIds: Sequence[str]
priorityIdsOnly: Optional[bool] = None
class ModelVersionsFilter(GraphQLBaseModel):
priority_ids: Sequence[str]
priority_ids_only: Optional[bool] = None
31 changes: 15 additions & 16 deletions src/specklepy/core/api/inputs/project_inputs.py
Original file line number Diff line number Diff line change
@@ -1,47 +1,46 @@
from typing import Optional, Sequence

from pydantic import BaseModel

from specklepy.core.api.enums import ProjectVisibility
from specklepy.core.api.models.graphql_base_model import GraphQLBaseModel


class ProjectCreateInput(BaseModel):
class ProjectCreateInput(GraphQLBaseModel):
name: Optional[str]
description: Optional[str]
visibility: Optional[ProjectVisibility]


class ProjectInviteCreateInput(BaseModel):
class ProjectInviteCreateInput(GraphQLBaseModel):
email: Optional[str]
role: Optional[str]
serverRole: Optional[str]
server_role: Optional[str]
userId: Optional[str]


class ProjectInviteUseInput(BaseModel):
class ProjectInviteUseInput(GraphQLBaseModel):
accept: bool
projectId: str
project_id: str
token: str


class ProjectModelsFilter(BaseModel):
class ProjectModelsFilter(GraphQLBaseModel):
contributors: Optional[Sequence[str]] = None
excludeIds: Optional[Sequence[str]] = None
exclude_ids: Optional[Sequence[str]] = None
ids: Optional[Sequence[str]] = None
onlyWithVersions: Optional[bool] = None
only_with_versions: Optional[bool] = None
search: Optional[str] = None
sourceApps: Optional[Sequence[str]] = None
source_apps: Optional[Sequence[str]] = None


class ProjectUpdateInput(BaseModel):
class ProjectUpdateInput(GraphQLBaseModel):
id: str
name: Optional[str] = None
description: Optional[str] = None
allowPublicComments: Optional[bool] = None
allow_public_comments: Optional[bool] = None
visibility: Optional[ProjectVisibility] = None


class ProjectUpdateRoleInput(BaseModel):
userId: str
projectId: str
class ProjectUpdateRoleInput(GraphQLBaseModel):
user_id: str
project_id: str
role: Optional[str]
8 changes: 4 additions & 4 deletions src/specklepy/core/api/inputs/user_inputs.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
from typing import Optional, Sequence

from pydantic import BaseModel
from specklepy.core.api.models.graphql_base_model import GraphQLBaseModel


class UserUpdateInput(BaseModel):
class UserUpdateInput(GraphQLBaseModel):
avatar: Optional[str] = None
bio: Optional[str] = None
company: Optional[str] = None
name: Optional[str] = None


class UserProjectsFilter(BaseModel):
class UserProjectsFilter(GraphQLBaseModel):
search: str
onlyWithRoles: Optional[Sequence[str]] = None
only_with_roles: Optional[Sequence[str]] = None
42 changes: 21 additions & 21 deletions src/specklepy/core/api/inputs/version_inputs.py
Original file line number Diff line number Diff line change
@@ -1,37 +1,37 @@
from typing import Optional, Sequence

from pydantic import BaseModel
from specklepy.core.api.models.graphql_base_model import GraphQLBaseModel


class UpdateVersionInput(BaseModel):
versionId: str
projectId: str
class UpdateVersionInput(GraphQLBaseModel):
version_id: str
project_id: str
message: Optional[str]


class MoveVersionsInput(BaseModel):
targetModelName: str
versionIds: Sequence[str]
projectId: str
class MoveVersionsInput(GraphQLBaseModel):
target_model_name: str
version_ids: Sequence[str]
project_id: str


class DeleteVersionsInput(BaseModel):
versionIds: Sequence[str]
projectId: str
class DeleteVersionsInput(GraphQLBaseModel):
version_ids: Sequence[str]
project_id: str


class CreateVersionInput(BaseModel):
objectId: str
modelId: str
projectId: str
class CreateVersionInput(GraphQLBaseModel):
object_id: str
model_id: str
project_id: str
message: Optional[str] = None
sourceApplication: Optional[str] = "py"
totalChildrenCount: Optional[int] = None
source_application: Optional[str] = "py"
total_children_count: Optional[int] = None
parents: Optional[Sequence[str]] = None


class MarkReceivedVersionInput(BaseModel):
versionId: str
projectId: str
sourceApplication: str
class MarkReceivedVersionInput(GraphQLBaseModel):
version_id: str
project_id: str
source_application: str
message: Optional[str] = None
Loading

0 comments on commit da6e2d9

Please sign in to comment.