Compare commits

...

13 Commits

Author SHA1 Message Date
Alper S. Soylu 4c381bd809 fix send stream object cases (#207)
* fix send stream object cases

* clean logs

* revert workaround

* revert unnecessary logic

* revert unnecessary logic

* rename set_user

---------

Co-authored-by: Soylu <alper.soylu@siemens.com>
2024-08-05 13:36:06 +01:00
Alper S. Soylu 8c3885ece8 Lazy loading for stream branches & commits (#200)
* only fetch branches on reload

* initial load

* load on stream selection

* refactor get_item_by_index

* fix resetting commit selection on default branch

* refactor load_stream_branches

* clean logs

* explicit return

---------

Co-authored-by: Soylu <alper.soylu@siemens.com>
Co-authored-by: Jedd Morgan <45512892+JR-Morgan@users.noreply.github.com>
2024-07-29 12:15:33 +01:00
Alper S. Soylu 15bd3f5070 fix resetting commit selection on default branch (#206)
Co-authored-by: Soylu <alper.soylu@siemens.com>
2024-07-28 23:22:07 +01:00
Jedd Morgan 6fd4571d34 update macos images (#203) 2024-07-16 19:42:34 +02:00
Jedd Morgan 5081177653 Small tweaks to installer (#202)
* Skip installing dependencies after initial install on production

* remove print

* remove requirements.txt on install

* small tweaks

---------

Co-authored-by: Soylu <alper.soylu@siemens.com>
2024-07-12 12:23:36 +01:00
Alper S. Soylu 0d0ca2c811 Skip installing dependencies after initial install (#199)
* Skip installing dependencies after initial install on production

* remove print

* remove requirements.txt on install

---------

Co-authored-by: Soylu <alper.soylu@siemens.com>
2024-07-12 12:18:40 +01:00
Jedd Morgan 230e27a162 Merge pull request #196 from overengineer/fix/resetting_selected_branch_workaround
Recover branch selection
2024-06-05 14:54:21 +01:00
Jedd Morgan 669fd19c2e Type hint polish 2024-06-05 14:52:32 +01:00
Soylu 139f8ccb33 type hints 2024-06-03 19:10:54 +03:00
Soylu 7f625bd468 check None item 2024-05-30 18:11:29 +03:00
Soylu 4d07ba7637 use object ids 2024-05-30 16:53:53 +03:00
Soylu e74a6cebb1 boundary check 2024-05-19 23:24:13 +03:00
Soylu 5e01d5a976 Recover branch selection 2024-05-16 18:19:36 +03:00
5 changed files with 166 additions and 40 deletions
+2 -1
View File
@@ -116,7 +116,8 @@ jobs:
build-installer-mac:
macos:
xcode: 12.5.1
xcode: 13.4.1
resource_class: macos.m1.medium.gen1
parameters:
runtime:
type: string
+20 -4
View File
@@ -138,7 +138,6 @@ def ensure_pip() -> None:
def get_requirements_path() -> Path:
# we assume that a requirements.txt exists next to the __init__.py file
path = Path(Path(__file__).parent, "requirements.txt")
assert path.exists()
return path
@@ -147,10 +146,22 @@ def install_requirements(host_application: str) -> None:
# script path. Here we'll install the
# dependencies
path = connector_installation_path(host_application)
print(f"Installing Speckle dependencies to {path}")
from subprocess import run
def debugger_is_active() -> bool:
"""Return if the debugger is currently active"""
return hasattr(sys, 'gettrace') and sys.gettrace() is not None
requirements_path = get_requirements_path()
is_debug = debugger_is_active()
if not is_debug and not requirements_path.exists():
print("Skipped installing dependencies")
return
print(f"Installing Speckle dependencies to {path}")
completed_process = run(
[
PYTHON_PATH,
@@ -165,16 +176,21 @@ def install_requirements(host_application: str) -> None:
"-t",
str(path),
"-r",
str(get_requirements_path()),
str(requirements_path),
],
capture_output=True,
text=True,
)
if completed_process.returncode != 0:
m = f"Failed to install dependenices through pip, got {completed_process.returncode} return code"
m = f"Failed to install dependencies through pip, got {completed_process.returncode} return code"
print(m)
raise Exception(m)
print("Successfully installed dependencies")
if not is_debug:
requirements_path.unlink()
def install_dependencies(host_application: str) -> None:
+6 -1
View File
@@ -33,7 +33,7 @@ from bpy_speckle.functions import (
)
from bpy_speckle.clients import speckle_clients
from bpy_speckle.operators.users import LoadUserStreams, add_user_stream
from bpy_speckle.properties.scene import SpeckleSceneSettings, SpeckleStreamObject, SpeckleUserObject, get_speckle
from bpy_speckle.properties.scene import SpeckleSceneSettings, SpeckleStreamObject, SpeckleUserObject, get_speckle, selection_state
from bpy_speckle.convert.util import ConversionSkippedException, add_to_hierarchy
from specklepy.core.api.models import Commit
from specklepy.core.api import operations, host_applications
@@ -380,6 +380,11 @@ class SendStreamObjects(bpy.types.Operator):
_report(f"Commit Created {sent_url}")
selection_state.selected_commit_id = COMMIT_ID
selection_state.selected_branch_id = branch.id
selection_state.selected_stream_id = stream.id
selection_state.selected_user_id = user.id
bpy.ops.speckle.load_user_streams() # refresh loaded commits
context.view_layer.update()
+19 -26
View File
@@ -6,7 +6,7 @@ import bpy
from bpy.types import Context
from bpy_speckle.functions import _report
from bpy_speckle.clients import speckle_clients
from bpy_speckle.properties.scene import SpeckleBranchObject, SpeckleCommitObject, SpeckleSceneSettings, SpeckleStreamObject, SpeckleUserObject, get_speckle
from bpy_speckle.properties.scene import SpeckleBranchObject, SpeckleCommitObject, SpeckleSceneSettings, SpeckleStreamObject, SpeckleUserObject, get_speckle, restore_selection_state
from specklepy.core.api.client import SpeckleClient
from specklepy.core.api.models import Stream
from specklepy.core.api.credentials import get_local_accounts, Account
@@ -137,28 +137,8 @@ def add_user_stream(user: SpeckleUserObject, stream: Stream):
_report(f"Adding stream {s.id} - {s.name}")
if not stream.branches:
return
# branches = [branch for branch in stream.branches.items if branch.name != "globals"]
for b in stream.branches.items:
branch = cast(SpeckleBranchObject, s.branches.add())
branch.name = b.name
branch.id = b.id
branch.description = b.description or ""
if not b.commits:
continue
for c in b.commits.items:
commit: SpeckleCommitObject = branch.commits.add()
commit.id = commit.name = c.id
commit.message = c.message or ""
commit.author_name = c.authorName
commit.author_id = c.authorId
commit.created_at = c.createdAt.strftime("%Y-%m-%d %H:%M:%S.%f%Z") if c.createdAt else ""
commit.source_application = str(c.sourceApplication)
commit.referenced_object = c.referencedObject
if stream.branches:
s.load_stream_branches(stream)
class LoadUserStreams(bpy.types.Operator):
@@ -195,12 +175,25 @@ class LoadUserStreams(bpy.types.Operator):
_report("Zero projects found")
return
active_stream_id = None
if active_stream := user.get_active_stream():
active_stream_id = active_stream.id
elif len(user.streams) > 0:
active_stream_id = user.streams[0].id
user.streams.clear()
for s in streams:
for i, s in enumerate(streams):
assert(s.id)
sstream = client.stream.get(id=s.id, branch_limit=self.branch_limit, commit_limit=10)
add_user_stream(user, sstream)
load_branches = s.id == active_stream_id if active_stream_id else i == 0
if load_branches:
sstream = client.stream.get(id=s.id, branch_limit=self.branch_limit, commit_limit=10)
add_user_stream(user, sstream)
else:
add_user_stream(user, s)
restore_selection_state(speckle)
bpy.context.view_layer.update()
+119 -8
View File
@@ -1,7 +1,8 @@
"""
Scene properties
"""
from typing import Iterable, Optional, Tuple, cast
from typing import Iterable, Optional, Tuple, Union, cast
from dataclasses import dataclass
import bpy
from bpy.props import (
StringProperty,
@@ -11,6 +12,9 @@ from bpy.props import (
IntProperty,
)
from bpy_speckle.clients import speckle_clients
from specklepy.core.api.models import Stream
class SpeckleSceneObject(bpy.types.PropertyGroup):
name: bpy.props.StringProperty(default="") # type: ignore
@@ -35,6 +39,11 @@ class SpeckleBranchObject(bpy.types.PropertyGroup):
]
return [("0", "<none>", "<none>", 0)]
def commit_update_hook(self, context: bpy.types.Context):
selection_state.selected_commit_id = SelectionState.get_item_id_by_index(self.commits, self.commit)
selection_state.selected_branch_id = self.id
# print(f"commit_update_hook: {selection_state.selected_commit_id=}, {selection_state.selected_branch_id=}")
name: StringProperty(default="main") # type: ignore
id: StringProperty(default="") # type: ignore
description: StringProperty(default="") # type: ignore
@@ -43,6 +52,7 @@ class SpeckleBranchObject(bpy.types.PropertyGroup):
name="Version",
description="Selected model version",
items=get_commits,
update=commit_update_hook,
) # type: ignore
def get_active_commit(self) -> Optional[SpeckleCommitObject]:
@@ -50,9 +60,30 @@ class SpeckleBranchObject(bpy.types.PropertyGroup):
if 0 <= selected_index < len(self.commits):
return self.commits[selected_index]
return None
class SpeckleStreamObject(bpy.types.PropertyGroup):
def load_stream_branches(self, sstream: Stream):
self.branches.clear()
# branches = [branch for branch in stream.branches.items if branch.name != "globals"]
for b in sstream.branches.items:
branch = cast(SpeckleBranchObject, self.branches.add())
branch.name = b.name
branch.id = b.id
branch.description = b.description or ""
if not b.commits:
continue
for c in b.commits.items:
commit: SpeckleCommitObject = branch.commits.add()
commit.id = commit.name = c.id
commit.message = c.message or ""
commit.author_name = c.authorName
commit.author_id = c.authorId
commit.created_at = c.createdAt.strftime("%Y-%m-%d %H:%M:%S.%f%Z") if c.createdAt else ""
commit.source_application = str(c.sourceApplication)
commit.referenced_object = c.referencedObject
def get_branches(self, context):
if self.branches:
BRANCHES = cast(Iterable[SpeckleBranchObject], self.branches)
@@ -62,6 +93,10 @@ class SpeckleStreamObject(bpy.types.PropertyGroup):
if branch.name != "globals"
]
return [("0", "<none>", "<none>", 0)]
def branch_update_hook(self, context: bpy.types.Context):
selection_state.selected_branch_id = SelectionState.get_item_id_by_index(self.branches, self.branch)
# print(f"branch_update_hook: {selection_state.selected_branch_id=}, {selection_state.selected_stream_id=}")
name: StringProperty(default="") # type: ignore
description: StringProperty(default="") # type: ignore
@@ -71,6 +106,7 @@ class SpeckleStreamObject(bpy.types.PropertyGroup):
name="Model",
description="Selected Model",
items=get_branches,
update=branch_update_hook,
) # type: ignore
def get_active_branch(self) -> Optional[SpeckleBranchObject]:
@@ -79,8 +115,20 @@ class SpeckleStreamObject(bpy.types.PropertyGroup):
return self.branches[selected_index]
return None
class SpeckleUserObject(bpy.types.PropertyGroup):
def fetch_stream_branches(self, context: bpy.types.Context, stream: SpeckleStreamObject):
speckle = context.scene.speckle
client = speckle_clients[int(speckle.active_user)]
sstream = client.stream.get(id=stream.id, branch_limit=100, commit_limit=10) # TODO: refactor magic numbers
stream.load_stream_branches(sstream)
def stream_update_hook(self, context: bpy.types.Context):
stream = SelectionState.get_item_by_index(self.streams, self.active_stream)
selection_state.selected_stream_id = stream.id
# print(f"stream_update_hook: {selection_state.selected_stream_id=}, {selection_state.selected_user_id=}")
if len(stream.branches) == 0: # do not reload on selection, same as the old behavior
self.fetch_stream_branches(context, stream)
server_name: StringProperty(default="SpeckleXYZ") # type: ignore
server_url: StringProperty(default="https://speckle.xyz") # type: ignore
id: StringProperty(default="") # type: ignore
@@ -88,13 +136,14 @@ class SpeckleUserObject(bpy.types.PropertyGroup):
email: StringProperty(default="user@speckle.xyz") # type: ignore
company: StringProperty(default="SpeckleSystems") # type: ignore
streams: CollectionProperty(type=SpeckleStreamObject) # type: ignore
active_stream: IntProperty(default=0) # type: ignore
active_stream: IntProperty(default=0, update=stream_update_hook) # type: ignore
def get_active_stream(self) -> Optional[SpeckleStreamObject]:
selected_index = int(self.active_stream)
if 0 <= selected_index < len(self.streams):
return self.streams[selected_index]
return None
class SpeckleSceneSettings(bpy.types.PropertyGroup):
def get_scripts(self, context):
@@ -118,14 +167,15 @@ class SpeckleSceneSettings(bpy.types.PropertyGroup):
for i, user in enumerate(USERS)
]
def set_user(self, context):
def user_update_hook(self, context):
bpy.ops.speckle.load_user_streams() # type: ignore
selection_state.selected_user_id = SelectionState.get_item_id_by_index(self.users, self.active_user)
active_user: EnumProperty(
items=get_users,
name="Account",
description="Select account",
update=set_user,
update=user_update_hook,
get=None,
set=None,
) # type: ignore
@@ -153,6 +203,8 @@ class SpeckleSceneSettings(bpy.types.PropertyGroup):
) # type: ignore
def get_active_user(self) -> Optional[SpeckleUserObject]:
if self.active_user is None:
return None
selected_index = int(self.active_user)
if 0 <= selected_index < len(self.users):
return self.users[selected_index]
@@ -197,4 +249,63 @@ def get_speckle(context: bpy.types.Context) -> SpeckleSceneSettings:
"""
Gets the speckle scene object
"""
return context.scene.speckle #type: ignore
return context.scene.speckle #type: ignore
@dataclass
class SelectionState:
selected_user_id : Optional[str] = None
selected_stream_id : Optional[str] = None
selected_branch_id : Optional[str] = None
selected_commit_id : Optional[str] = None
@staticmethod
def get_item_id_by_index(collection: bpy.types.PropertyGroup, index: Union[str, int]) -> Optional[str]:
if item := SelectionState.get_item_by_index(collection, index):
return item.id
return None
@staticmethod
def get_item_by_index(collection: bpy.types.PropertyGroup, index: Union[str, int]) -> Optional[bpy.types.PropertyGroup]:
items = collection.values()
i = int(index)
if 0 <= i <= len(items):
return items[i]
return None
@staticmethod
def get_item_index_by_id(collection: Iterable[SpeckleCommitObject], id: Optional[str]) -> Optional[str]:
for index, item in enumerate(collection):
if item.id == id:
return str(index)
return None
selection_state = SelectionState()
def restore_selection_state(speckle: SpeckleSceneSettings) -> None:
# Restore branch selection state
if selection_state.selected_branch_id != None:
(active_user, active_stream) = speckle.validate_stream_selection()
# print(f"restore_selection_state: {active_user.id=}, {active_stream.id=}")
# print(f"restore_selection_state: {selection_state.selected_user_id=}, {selection_state.selected_stream_id=}, {selection_state.selected_branch_id=}, {selection_state.selected_commit_id=}")
is_same_user = active_user.id == selection_state.selected_user_id
if is_same_user:
active_user.active_stream = int(SelectionState.get_item_index_by_id(active_user.streams, selection_state.selected_stream_id))
active_stream = SelectionState.get_item_by_index(active_user.streams, active_user.active_stream)
if branch := SelectionState.get_item_index_by_id(active_stream.branches, selection_state.selected_branch_id):
active_stream.branch = branch
# Restore commit selection state
if selection_state.selected_commit_id != None:
(active_user, active_stream, active_branch) = speckle.validate_branch_selection()
# print(f"restore_selection_state: {active_user.id=}, {active_stream.id=}, {active_branch.id=}")
# print(f"restore_selection_state: {selection_state.selected_user_id=}, {selection_state.selected_stream_id=}, {selection_state.selected_branch_id=}, {selection_state.selected_commit_id=}")
is_same_user = active_user.id == selection_state.selected_user_id
is_same_stream = active_stream.id == selection_state.selected_stream_id
is_same_branch = active_branch.id == selection_state.selected_branch_id
if is_same_user and is_same_stream and is_same_branch:
if commit := SelectionState.get_item_index_by_id(active_branch.commits, selection_state.selected_commit_id):
active_branch.commit = commit