Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a8a5296d7e | |||
| 4f82c0f43d | |||
| f5e024c8ce |
@@ -12,6 +12,7 @@ from specklepy.core.api.models import (
|
||||
User,
|
||||
)
|
||||
from specklepy.core.api.models.current import (
|
||||
LimitedWorkspace,
|
||||
PermissionCheckResult,
|
||||
ProjectWithPermissions,
|
||||
Workspace,
|
||||
@@ -94,7 +95,7 @@ class ActiveUserResource(CoreResource):
|
||||
metrics.track(metrics.SDK, self.account, {"name": "Active User Get Workspaces"})
|
||||
return super().get_workspaces(limit, cursor, filter)
|
||||
|
||||
def get_active_workspace(self) -> Optional[Workspace]:
|
||||
def get_active_workspace(self) -> Optional[LimitedWorkspace]:
|
||||
metrics.track(
|
||||
metrics.SDK, self.account, {"name": "Active User Get Active Workspace"}
|
||||
)
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
from datetime import datetime
|
||||
from typing import List
|
||||
|
||||
import httpx
|
||||
from pydantic import AliasGenerator, BaseModel, ConfigDict, HttpUrl
|
||||
from pydantic.alias_generators import to_pascal
|
||||
|
||||
|
||||
class ConnectorFeedBaseModel(BaseModel):
|
||||
"""
|
||||
Parent class for all Connector Feed Object Model classes
|
||||
Sets-up a pydantic config to serialize properties using a pascal case alias
|
||||
"""
|
||||
|
||||
model_config = ConfigDict(
|
||||
alias_generator=AliasGenerator(
|
||||
validation_alias=to_pascal,
|
||||
),
|
||||
populate_by_name=True,
|
||||
)
|
||||
|
||||
|
||||
class ConnectorVersion(ConnectorFeedBaseModel):
|
||||
number: str
|
||||
url: HttpUrl
|
||||
os: int # this is an enum, it's properly defined in the old v2 SDK (used by Speckle.Manager.Feed) # noqa: E501
|
||||
architecture: int # These are enums, they are properly defined in the old v2 SDK (used by Speckle.Manager.Feed) # noqa: E501
|
||||
date: datetime
|
||||
prerelease: bool
|
||||
|
||||
|
||||
class ConnectorVersions(ConnectorFeedBaseModel):
|
||||
versions: List[ConnectorVersion]
|
||||
|
||||
|
||||
def get_latest_version(host_app_slug: str, allow_pre_release: bool) -> ConnectorVersion:
|
||||
"""
|
||||
Fetches the JSON feed for the given connector slug and
|
||||
Returns the latest version by date - Note, it does not consider semvers!
|
||||
|
||||
Arguments:
|
||||
host_app_slug {str} -- the host app slug to query for
|
||||
allow_pre_release {bool} -- if false, only stable releases will be considered
|
||||
Raises:
|
||||
HTTPStatusError: if http request failed
|
||||
ValidationError: response was not valid json
|
||||
ValueError: The feed contained no connector versions
|
||||
"""
|
||||
connector_versions = get_connector_versions(host_app_slug).versions
|
||||
filtered_versions = [
|
||||
v for v in connector_versions if allow_pre_release or not v.prerelease
|
||||
]
|
||||
|
||||
return max(filtered_versions, key=lambda x: x.date)
|
||||
|
||||
|
||||
def get_connector_versions(host_app_slug: str) -> ConnectorVersions:
|
||||
"""
|
||||
Fetches the JSON feed for the given slug (v3 feeds only)
|
||||
Raises:
|
||||
HTTPStatusError: if http request failed
|
||||
ValidationError: response was not valid json
|
||||
"""
|
||||
url = f"https://releases.speckle.dev/manager2/feeds/{host_app_slug.lower()}-v3.json"
|
||||
|
||||
res = httpx.get(url).raise_for_status()
|
||||
|
||||
feed_data = ConnectorVersions.model_validate_json(res.text)
|
||||
|
||||
return feed_data
|
||||
@@ -213,15 +213,18 @@ class WorkspaceCreationState(GraphQLBaseModel):
|
||||
completed: bool
|
||||
|
||||
|
||||
class Workspace(GraphQLBaseModel):
|
||||
class LimitedWorkspace(GraphQLBaseModel):
|
||||
id: str
|
||||
name: str
|
||||
role: Optional[str]
|
||||
slug: str
|
||||
logo: Optional[str]
|
||||
description: Optional[str]
|
||||
|
||||
|
||||
class Workspace(LimitedWorkspace):
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
read_only: bool
|
||||
description: Optional[str]
|
||||
creation_state: Optional[WorkspaceCreationState]
|
||||
permissions: WorkspacePermissionChecks
|
||||
|
||||
@@ -14,6 +14,7 @@ from specklepy.core.api.models import (
|
||||
User,
|
||||
)
|
||||
from specklepy.core.api.models.current import (
|
||||
LimitedWorkspace,
|
||||
PermissionCheckResult,
|
||||
ProjectWithPermissions,
|
||||
Workspace,
|
||||
@@ -295,7 +296,7 @@ class ActiveUserResource(ResourceBase):
|
||||
|
||||
return response.data.data
|
||||
|
||||
def get_active_workspace(self) -> Optional[Workspace]:
|
||||
def get_active_workspace(self) -> Optional[LimitedWorkspace]:
|
||||
"""
|
||||
This feature is only available on Workspace enabled servers (server versions
|
||||
>=2.23.17) e.g. app.speckle.systems
|
||||
@@ -310,29 +311,15 @@ class ActiveUserResource(ResourceBase):
|
||||
role
|
||||
slug
|
||||
logo
|
||||
createdAt
|
||||
updatedAt
|
||||
readOnly
|
||||
description
|
||||
creationState
|
||||
{
|
||||
completed
|
||||
}
|
||||
permissions {
|
||||
canCreateProject {
|
||||
authorized
|
||||
code
|
||||
message
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
""" # noqa: E501
|
||||
"""
|
||||
)
|
||||
|
||||
response = self.make_request_and_parse_response(
|
||||
DataResponse[Optional[DataResponse[Optional[Workspace]]]],
|
||||
DataResponse[Optional[DataResponse[Optional[LimitedWorkspace]]]],
|
||||
QUERY,
|
||||
)
|
||||
|
||||
|
||||
@@ -199,8 +199,9 @@ class BaseObjectSerializer:
|
||||
|
||||
# write detached or root objects to transports
|
||||
if detached and self.write_transports:
|
||||
serialized_data = ujson.dumps(object_builder)
|
||||
for t in self.write_transports:
|
||||
t.save_object(id=obj_id, serialized_object=ujson.dumps(object_builder))
|
||||
t.save_object(id=obj_id, serialized_object=serialized_data)
|
||||
|
||||
del self.lineage[-1]
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
import pytest
|
||||
from httpx import HTTPStatusError
|
||||
|
||||
from specklepy.core.api.connector_versions import (
|
||||
ConnectorVersion,
|
||||
ConnectorVersions,
|
||||
get_connector_versions,
|
||||
get_latest_version,
|
||||
)
|
||||
|
||||
# NOTE: the tests in this file are testing against the live releases.speckle.dev server
|
||||
# url defined in get_connector_versions.
|
||||
|
||||
|
||||
def test_connector_versions():
|
||||
res = get_connector_versions("blender")
|
||||
|
||||
assert isinstance(res, ConnectorVersions)
|
||||
assert res.versions # Assuming the feed is not empty
|
||||
|
||||
|
||||
def test_get_latest_version_throws_no_slug():
|
||||
with pytest.raises(HTTPStatusError) as ex:
|
||||
get_latest_version("non-existent-connector!", True)
|
||||
|
||||
assert "404" in str(ex.value)
|
||||
|
||||
|
||||
def test_get_latest_version():
|
||||
res = get_latest_version("blender", False)
|
||||
|
||||
assert isinstance(res, ConnectorVersion)
|
||||
Reference in New Issue
Block a user