Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 89280acf53 | |||
| 78c55b787f | |||
| 34f2dc2ab6 | |||
| d71b616e2b | |||
| 35750f12c5 | |||
| 82b6dbbe78 | |||
| 883be4b27b | |||
| 8dcc67fb31 | |||
| ed84820995 | |||
| 5c3dcb7bc0 | |||
| a0e10aae99 | |||
| bbea2a0d76 | |||
| a05ac3479b | |||
| 0bd972945e | |||
| f200544065 | |||
| 68ce9823ae | |||
| a920352407 |
@@ -2,7 +2,7 @@ repos:
|
||||
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||||
hooks:
|
||||
- id: ruff
|
||||
rev: v0.1.6
|
||||
rev: v0.8.2
|
||||
|
||||
- repo: https://github.com/commitizen-tools/commitizen
|
||||
hooks:
|
||||
@@ -13,12 +13,12 @@ repos:
|
||||
rev: v3.13.0
|
||||
|
||||
- repo: https://github.com/pycqa/isort
|
||||
rev: 5.12.0
|
||||
rev: 5.13.2
|
||||
hooks:
|
||||
- id: isort
|
||||
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 23.11.0
|
||||
rev: 24.10.0
|
||||
hooks:
|
||||
- id: black
|
||||
# It is recommended to specify the latest version of Python
|
||||
|
||||
Generated
+788
-706
File diff suppressed because it is too large
Load Diff
+7
-8
@@ -15,7 +15,7 @@ packages = [
|
||||
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = ">=3.8.0, <4.0"
|
||||
python = ">=3.9.0, <4.0"
|
||||
pydantic = "^2.5"
|
||||
appdirs = "^1.4.4"
|
||||
gql = { extras = ["requests", "websockets"], version = "^3.3.0" }
|
||||
@@ -26,19 +26,19 @@ attrs = "^23.1.0"
|
||||
httpx = "^0.25.0"
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
black = "23.11.0"
|
||||
isort = "^5.7.0"
|
||||
black = "24.10.0"
|
||||
isort = "^5.13.2"
|
||||
pytest = "^7.1.3"
|
||||
pytest-asyncio = "^0.23.0"
|
||||
pytest-ordering = "^0.6"
|
||||
pytest-cov = "^3.0.0"
|
||||
devtools = "^0.8.0"
|
||||
pylint = "^2.14.4"
|
||||
pylint = "^3.3.2"
|
||||
pydantic-settings = "^2.3.0"
|
||||
mypy = "^0.982"
|
||||
pre-commit = "^2.20.0"
|
||||
commitizen = "^2.38.0"
|
||||
ruff = "^0.4.4"
|
||||
commitizen = "^3.13.0"
|
||||
ruff = "^0.8.2"
|
||||
types-deprecated = "^1.2.9"
|
||||
types-ujson = "^5.6.0.0"
|
||||
types-requests = "^2.28.11.5"
|
||||
@@ -60,8 +60,7 @@ exclude = '''
|
||||
'''
|
||||
include = '\.pyi?$'
|
||||
line-length = 88
|
||||
target-version = ["py37", "py38", "py39", "py310", "py311"]
|
||||
|
||||
target-version = ["py39", "py310", "py311", "py312", "py313"]
|
||||
|
||||
[tool.commitizen]
|
||||
name = "cz_conventional_commits"
|
||||
|
||||
@@ -101,8 +101,17 @@ class AutomationContext:
|
||||
commit = self.speckle_client.commit.get(
|
||||
self.automation_run_data.project_id, version_id
|
||||
)
|
||||
if not commit.referencedObject:
|
||||
raise ValueError("The commit has no referencedObject, cannot receive it.")
|
||||
if not commit or not commit.referencedObject:
|
||||
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}
|
||||
"""
|
||||
)
|
||||
base = operations.receive(
|
||||
commit.referencedObject, self._server_transport, self._memory_transport
|
||||
)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""Some useful helpers for working with automation data."""
|
||||
|
||||
import secrets
|
||||
import string
|
||||
|
||||
@@ -21,10 +22,10 @@ class TestAutomationEnvironment(BaseSettings):
|
||||
extra="ignore",
|
||||
)
|
||||
|
||||
token: str = Field()
|
||||
server_url: str = Field()
|
||||
project_id: str = Field()
|
||||
automation_id: str = Field()
|
||||
token: str = Field(default="")
|
||||
server_url: str = Field(default="")
|
||||
project_id: str = Field(default="")
|
||||
automation_id: str = Field(default="")
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
|
||||
@@ -61,15 +61,13 @@ def _parse_input_data(
|
||||
def execute_automate_function(
|
||||
automate_function: AutomateFunction[T],
|
||||
input_schema: type[T],
|
||||
) -> None:
|
||||
...
|
||||
) -> None: ...
|
||||
|
||||
|
||||
@overload
|
||||
def execute_automate_function(
|
||||
automate_function: AutomateFunctionWithoutInputs,
|
||||
) -> None:
|
||||
...
|
||||
) -> None: ...
|
||||
|
||||
|
||||
class AutomateGenerateJsonSchema(GenerateJsonSchema):
|
||||
@@ -146,16 +144,14 @@ def run_function(
|
||||
automation_context: AutomationContext,
|
||||
automate_function: AutomateFunction[T],
|
||||
inputs: T,
|
||||
) -> AutomationContext:
|
||||
...
|
||||
) -> AutomationContext: ...
|
||||
|
||||
|
||||
@overload
|
||||
def run_function(
|
||||
automation_context: AutomationContext,
|
||||
automate_function: AutomateFunctionWithoutInputs,
|
||||
) -> AutomationContext:
|
||||
...
|
||||
) -> AutomationContext: ...
|
||||
|
||||
|
||||
def run_function(
|
||||
|
||||
@@ -7,12 +7,12 @@ from specklepy.api.resources import (
|
||||
OtherUserResource,
|
||||
ProjectInviteResource,
|
||||
ProjectResource,
|
||||
ServerResource,
|
||||
SubscriptionResource,
|
||||
VersionResource,
|
||||
branch,
|
||||
commit,
|
||||
object,
|
||||
server,
|
||||
stream,
|
||||
subscriptions,
|
||||
user,
|
||||
@@ -69,7 +69,7 @@ class SpeckleClient(CoreSpeckleClient):
|
||||
self.account = Account()
|
||||
|
||||
def _init_resources(self) -> None:
|
||||
self.server = server.Resource(
|
||||
self.server = ServerResource(
|
||||
account=self.account, basepath=self.url, client=self.httpclient
|
||||
)
|
||||
|
||||
|
||||
@@ -3,8 +3,7 @@ from typing import List, Optional, overload
|
||||
|
||||
from deprecated import deprecated
|
||||
|
||||
from specklepy.core.api.inputs.project_inputs import UserProjectsFilter
|
||||
from specklepy.core.api.inputs.user_inputs import UserUpdateInput
|
||||
from specklepy.core.api.inputs.user_inputs import UserProjectsFilter, UserUpdateInput
|
||||
from specklepy.core.api.models import (
|
||||
PendingStreamCollaborator,
|
||||
Project,
|
||||
@@ -44,12 +43,10 @@ class ActiveUserResource(CoreResource):
|
||||
company: Optional[str] = None,
|
||||
bio: Optional[str] = None,
|
||||
avatar: Optional[str] = None,
|
||||
) -> User:
|
||||
...
|
||||
) -> User: ...
|
||||
|
||||
@overload
|
||||
def update(self, *, input: UserUpdateInput) -> User:
|
||||
...
|
||||
def update(self, *, input: UserUpdateInput) -> User: ...
|
||||
|
||||
def update(
|
||||
self,
|
||||
|
||||
@@ -4,6 +4,6 @@ from specklepy.api.resources import ServerResource
|
||||
from specklepy.core.api.models.deprecated import FE1_DEPRECATION_VERSION
|
||||
|
||||
|
||||
@deprecated(reason="Renamed to ActiveUserResource", version=FE1_DEPRECATION_VERSION)
|
||||
@deprecated(reason="Renamed to ServerResource", version=FE1_DEPRECATION_VERSION)
|
||||
class Resource(ServerResource):
|
||||
"""Renamed to ServerResource"""
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
from specklepy.core.api.inputs.model_inputs import (
|
||||
CreateModelInput,
|
||||
DeleteModelInput,
|
||||
ModelVersionsFilter,
|
||||
UpdateModelInput,
|
||||
)
|
||||
from specklepy.core.api.inputs.project_inputs import (
|
||||
ProjectCreateInput,
|
||||
ProjectInviteCreateInput,
|
||||
ProjectInviteUseInput,
|
||||
ProjectModelsFilter,
|
||||
ProjectUpdateInput,
|
||||
ProjectUpdateRoleInput,
|
||||
)
|
||||
from specklepy.core.api.inputs.user_inputs import UserProjectsFilter, UserUpdateInput
|
||||
from specklepy.core.api.inputs.version_inputs import (
|
||||
CreateVersionInput,
|
||||
DeleteVersionsInput,
|
||||
MarkReceivedVersionInput,
|
||||
MoveVersionsInput,
|
||||
UpdateVersionInput,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"CreateModelInput",
|
||||
"DeleteModelInput",
|
||||
"UpdateModelInput",
|
||||
"ModelVersionsFilter",
|
||||
"ProjectCreateInput",
|
||||
"ProjectInviteCreateInput",
|
||||
"ProjectInviteUseInput",
|
||||
"ProjectModelsFilter",
|
||||
"ProjectUpdateInput",
|
||||
"ProjectUpdateRoleInput",
|
||||
"UserProjectsFilter",
|
||||
"UserUpdateInput",
|
||||
"UpdateVersionInput",
|
||||
"MoveVersionsInput",
|
||||
"DeleteVersionsInput",
|
||||
"CreateVersionInput",
|
||||
"MarkReceivedVersionInput",
|
||||
]
|
||||
@@ -45,8 +45,3 @@ class ProjectUpdateRoleInput(BaseModel):
|
||||
userId: str
|
||||
projectId: str
|
||||
role: Optional[str]
|
||||
|
||||
|
||||
class UserProjectsFilter(BaseModel):
|
||||
search: str
|
||||
onlyWithRole: Optional[Sequence[str]] = None
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import Optional
|
||||
from typing import Optional, Sequence
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
@@ -8,3 +8,8 @@ class UserUpdateInput(BaseModel):
|
||||
bio: Optional[str] = None
|
||||
company: Optional[str] = None
|
||||
name: Optional[str] = None
|
||||
|
||||
|
||||
class UserProjectsFilter(BaseModel):
|
||||
search: str
|
||||
onlyWithRoles: Optional[Sequence[str]] = None
|
||||
|
||||
@@ -126,7 +126,7 @@ class Version(BaseModel):
|
||||
|
||||
|
||||
class Model(BaseModel):
|
||||
author: LimitedUser
|
||||
author: Optional[LimitedUser]
|
||||
createdAt: datetime
|
||||
description: Optional[str]
|
||||
displayName: str
|
||||
|
||||
@@ -4,8 +4,7 @@ from typing import List, Optional, overload
|
||||
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.inputs.user_inputs import UserProjectsFilter, UserUpdateInput
|
||||
from specklepy.core.api.models import (
|
||||
ActivityCollection,
|
||||
PendingStreamCollaborator,
|
||||
@@ -100,12 +99,10 @@ class ActiveUserResource(ResourceBase):
|
||||
company: Optional[str] = None,
|
||||
bio: Optional[str] = None,
|
||||
avatar: Optional[str] = None,
|
||||
) -> User:
|
||||
...
|
||||
) -> User: ...
|
||||
|
||||
@overload
|
||||
def update(self, *, input: UserUpdateInput) -> User:
|
||||
...
|
||||
def update(self, *, input: UserUpdateInput) -> User: ...
|
||||
|
||||
def update(
|
||||
self,
|
||||
|
||||
@@ -127,9 +127,11 @@ class ModelResource(ResourceBase):
|
||||
"modelId": model_id,
|
||||
"versionsLimit": versions_limit,
|
||||
"versionsCursor": versions_cursor,
|
||||
"versionsFilter": versions_filter.model_dump(warnings="error")
|
||||
if versions_filter
|
||||
else None,
|
||||
"versionsFilter": (
|
||||
versions_filter.model_dump(warnings="error")
|
||||
if versions_filter
|
||||
else None
|
||||
),
|
||||
}
|
||||
|
||||
return self.make_request_and_parse_response(
|
||||
@@ -179,9 +181,9 @@ class ModelResource(ResourceBase):
|
||||
"projectId": project_id,
|
||||
"modelsLimit": models_limit,
|
||||
"modelsCursor": models_cursor,
|
||||
"modelsFilter": models_filter.model_dump(warnings="error")
|
||||
if models_filter
|
||||
else None,
|
||||
"modelsFilter": (
|
||||
models_filter.model_dump(warnings="error") if models_filter else None
|
||||
),
|
||||
}
|
||||
|
||||
return self.make_request_and_parse_response(
|
||||
|
||||
@@ -108,9 +108,9 @@ class ProjectResource(ResourceBase):
|
||||
"projectId": project_id,
|
||||
"modelsLimit": models_limit,
|
||||
"modelsCursor": models_cursor,
|
||||
"modelsFilter": models_filter.model_dump(warnings="error")
|
||||
if models_filter
|
||||
else None,
|
||||
"modelsFilter": (
|
||||
models_filter.model_dump(warnings="error") if models_filter else None
|
||||
),
|
||||
}
|
||||
|
||||
return self.make_request_and_parse_response(
|
||||
|
||||
@@ -111,7 +111,7 @@ class Resource(ResourceBase):
|
||||
query = gql(
|
||||
"""
|
||||
query User($stream_limit: Int!) {
|
||||
user {
|
||||
activeUser {
|
||||
id
|
||||
bio
|
||||
name
|
||||
@@ -149,7 +149,7 @@ class Resource(ResourceBase):
|
||||
params = {"stream_limit": stream_limit}
|
||||
|
||||
return self.make_request(
|
||||
query=query, params=params, return_type=["user", "streams", "items"]
|
||||
query=query, params=params, return_type=["activeUser", "streams", "items"]
|
||||
)
|
||||
|
||||
@deprecated(reason=FE1_DEPRECATION_REASON, version=FE1_DEPRECATION_VERSION)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"""
|
||||
Provides uniform and consistent path helpers for `specklepy`
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
@@ -295,9 +295,9 @@ class RevitParameter(Base, speckle_type="Objects.BuiltElements.Revit.Parameter")
|
||||
value: Any = None
|
||||
applicationUnitType: Optional[str] = None # eg UnitType UT_Length
|
||||
applicationUnit: Optional[str] = None # DisplayUnitType eg DUT_MILLIMITERS
|
||||
applicationInternalName: Optional[
|
||||
str
|
||||
] = None # BuiltInParameterName or GUID for shared parameter
|
||||
applicationInternalName: Optional[str] = (
|
||||
None # BuiltInParameterName or GUID for shared parameter
|
||||
)
|
||||
isShared: bool = False
|
||||
isReadOnly: bool = False
|
||||
isTypeParameter: bool = False
|
||||
|
||||
@@ -2,7 +2,7 @@ import pytest
|
||||
|
||||
from specklepy.api.client import SpeckleClient
|
||||
from specklepy.core.api.inputs.project_inputs import ProjectCreateInput
|
||||
from specklepy.core.api.inputs.user_inputs import UserUpdateInput
|
||||
from specklepy.core.api.inputs.user_inputs import UserProjectsFilter, UserUpdateInput
|
||||
from specklepy.core.api.models import ResourceCollection, User
|
||||
|
||||
|
||||
@@ -42,3 +42,21 @@ class TestActiveUserResource:
|
||||
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)
|
||||
|
||||
def test_active_user_get_projects_with_filter(self, client: SpeckleClient):
|
||||
# Since the client may be reused for other tests,
|
||||
# this test does rely on no other test creating a project with "Search for me" in its name
|
||||
p1 = client.project.create(
|
||||
ProjectCreateInput(name="Search for me!", description=None, visibility=None)
|
||||
)
|
||||
_ = client.project.create(
|
||||
ProjectCreateInput(name="But not me!", description=None, visibility=None)
|
||||
)
|
||||
filter = UserProjectsFilter(search="Search for me")
|
||||
|
||||
res = client.active_user.get_projects(filter=filter)
|
||||
|
||||
assert isinstance(res, ResourceCollection)
|
||||
assert len(res.items) == 1
|
||||
assert res.totalCount == 1
|
||||
assert res.items[0].id == p1.id
|
||||
|
||||
@@ -6,7 +6,10 @@ from specklepy.core.api.inputs.model_inputs import (
|
||||
DeleteModelInput,
|
||||
UpdateModelInput,
|
||||
)
|
||||
from specklepy.core.api.inputs.project_inputs import ProjectCreateInput
|
||||
from specklepy.core.api.inputs.project_inputs import (
|
||||
ProjectCreateInput,
|
||||
ProjectModelsFilter,
|
||||
)
|
||||
from specklepy.core.api.models.current import (
|
||||
Model,
|
||||
Project,
|
||||
@@ -65,6 +68,18 @@ class TestModelResource:
|
||||
assert result.createdAt == test_model.createdAt
|
||||
assert result.updatedAt == test_model.updatedAt
|
||||
|
||||
def test_models_get_with_filter(
|
||||
self, client: SpeckleClient, test_model: Model, test_project: Project
|
||||
):
|
||||
filter = ProjectModelsFilter(search=test_model.name)
|
||||
|
||||
result = client.model.get_models(test_project.id, models_filter=filter)
|
||||
|
||||
assert isinstance(result, ResourceCollection)
|
||||
assert len(result.items) == 1
|
||||
assert result.totalCount == 1
|
||||
assert result.items[0].id == test_model.id
|
||||
|
||||
def test_get_models(
|
||||
self, client: SpeckleClient, test_project: Project, test_model: Model
|
||||
):
|
||||
@@ -82,6 +97,20 @@ class TestModelResource:
|
||||
|
||||
assert isinstance(result, ProjectWithModels)
|
||||
assert result.id == test_project.id
|
||||
assert isinstance(result.models, ResourceCollection)
|
||||
assert len(result.models.items) == 1
|
||||
assert result.models.totalCount == 1
|
||||
assert result.models.items[0].id == test_model.id
|
||||
|
||||
def test_project_get_models_with_filter(
|
||||
self, client: SpeckleClient, test_project: Project, test_model: Model
|
||||
):
|
||||
filter = ProjectModelsFilter(search=test_model.name)
|
||||
result = client.project.get_with_models(test_project.id, models_filter=filter)
|
||||
|
||||
assert isinstance(result, ProjectWithModels)
|
||||
assert result.id == test_project.id
|
||||
assert isinstance(result.models, ResourceCollection)
|
||||
assert len(result.models.items) == 1
|
||||
assert result.models.totalCount == 1
|
||||
assert result.models.items[0].id == test_model.id
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import pytest
|
||||
|
||||
from specklepy.api.client import SpeckleClient
|
||||
from specklepy.core.api.inputs.model_inputs import CreateModelInput
|
||||
from specklepy.core.api.inputs.model_inputs import CreateModelInput, ModelVersionsFilter
|
||||
from specklepy.core.api.inputs.project_inputs import ProjectCreateInput
|
||||
from specklepy.core.api.inputs.version_inputs import (
|
||||
DeleteVersionsInput,
|
||||
@@ -76,6 +76,26 @@ class TestVersionResource:
|
||||
assert result.totalCount == 1
|
||||
assert result.items[0].id == test_version.id
|
||||
|
||||
def test_versions_get_with_filter(
|
||||
self,
|
||||
client: SpeckleClient,
|
||||
test_model_1: Model,
|
||||
test_project: Project,
|
||||
test_version: Version,
|
||||
):
|
||||
filter = ModelVersionsFilter(
|
||||
priorityIds=[test_version.id], priorityIdsOnly=True
|
||||
)
|
||||
|
||||
result = client.version.get_versions(
|
||||
test_model_1.id, test_project.id, filter=filter
|
||||
)
|
||||
|
||||
assert isinstance(result, ResourceCollection)
|
||||
assert len(result.items) == 1
|
||||
assert result.totalCount == 1
|
||||
assert result.items[0].id == test_version.id
|
||||
|
||||
def test_version_received(
|
||||
self, client: SpeckleClient, test_version: Version, test_project: Project
|
||||
):
|
||||
@@ -103,6 +123,27 @@ class TestVersionResource:
|
||||
assert result.versions.totalCount == 1
|
||||
assert result.versions.items[0].id == test_version.id
|
||||
|
||||
def test_model_get_with_versions_with_filter(
|
||||
self,
|
||||
client: SpeckleClient,
|
||||
test_model_1: Model,
|
||||
test_project: Project,
|
||||
test_version: Version,
|
||||
):
|
||||
filter = ModelVersionsFilter(
|
||||
priorityIds=[test_version.id], priorityIdsOnly=True
|
||||
)
|
||||
|
||||
result = client.model.get_with_versions(
|
||||
test_model_1.id, test_project.id, versions_filter=filter
|
||||
)
|
||||
|
||||
assert isinstance(result, ModelWithVersions)
|
||||
assert len(result.versions.items) == 1
|
||||
assert result.versions.totalCount == 1
|
||||
assert isinstance(result.versions, ResourceCollection)
|
||||
assert result.versions.items[0].id == test_version.id
|
||||
|
||||
def test_version_update(
|
||||
self, client: SpeckleClient, test_version: Version, test_project: Project
|
||||
):
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""Run integration tests with a speckle server."""
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import Dict
|
||||
|
||||
@@ -72,7 +72,7 @@ def line(point, interval):
|
||||
start=point,
|
||||
end=point,
|
||||
domain=interval,
|
||||
units="none"
|
||||
units="none",
|
||||
# These attributes are not handled in C#
|
||||
# bbox=None,
|
||||
# length=None
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"""
|
||||
Provides uniform and consistent path helpers for `specklepy`
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
from importlib import import_module, invalidate_caches
|
||||
|
||||
Reference in New Issue
Block a user