chore: fix all ruff issues
This commit is contained in:
+1
-1
@@ -5,7 +5,7 @@ import sys
|
||||
def patch(tag):
|
||||
print(f"Patching version: {tag}")
|
||||
|
||||
with open("pyproject.toml", "r") as f:
|
||||
with open("pyproject.toml") as f:
|
||||
lines = f.readlines()
|
||||
|
||||
if "version" not in lines[2]:
|
||||
|
||||
@@ -96,7 +96,8 @@ class AutomationContext:
|
||||
|
||||
def receive_version(self) -> Base:
|
||||
"""Receive the Speckle project version that triggered this automation run."""
|
||||
# TODO: this is a quick hack to keep implementation consistency. Move to proper receive many versions
|
||||
# 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
|
||||
@@ -264,7 +265,8 @@ class AutomationContext:
|
||||
|
||||
if not path_obj.exists():
|
||||
raise ValueError("The given file path doesn't exist")
|
||||
files = {path_obj.name: open(str(path_obj), "rb")}
|
||||
|
||||
files = {path_obj.name: path_obj.open("rb")}
|
||||
|
||||
url = (
|
||||
f"{self.automation_run_data.speckle_server_url}api/stream/"
|
||||
|
||||
@@ -128,7 +128,8 @@ def execute_automate_function(
|
||||
automate_function, # type: ignore
|
||||
)
|
||||
|
||||
# if we've gotten this far, the execution should technically be completed as expected
|
||||
# if we've gotten this far,
|
||||
# the execution should technically be completed as expected
|
||||
# thus exiting with 0 is the schemantically correct thing to do
|
||||
exit_code = (
|
||||
1 if automation_context.run_status == AutomationStatus.EXCEPTION else 0
|
||||
@@ -190,4 +191,4 @@ def run_function(
|
||||
if not automation_context.context_view:
|
||||
automation_context.set_context_view()
|
||||
automation_context.report_run_status()
|
||||
return automation_context
|
||||
return automation_context
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import contextlib
|
||||
|
||||
from deprecated import deprecated
|
||||
|
||||
from specklepy.api.credentials import Account
|
||||
@@ -40,7 +42,8 @@ class SpeckleClient(CoreSpeckleClient):
|
||||
client = SpeckleClient(host="app.speckle.systems") # or whatever your host is
|
||||
# client = SpeckleClient(host="localhost:3000", use_ssl=False) or use local server
|
||||
|
||||
# authenticate the client with an account (account has been added in Speckle Manager)
|
||||
# authenticate the client with an account
|
||||
# (account has been added in Speckle Manager)
|
||||
account = get_default_account()
|
||||
client.authenticate_with_account(account)
|
||||
|
||||
@@ -74,10 +77,9 @@ class SpeckleClient(CoreSpeckleClient):
|
||||
)
|
||||
|
||||
server_version = None
|
||||
try:
|
||||
|
||||
with contextlib.suppress(Exception):
|
||||
server_version = self.server.version()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
self.other_user = OtherUserResource(
|
||||
account=self.account,
|
||||
|
||||
@@ -53,7 +53,9 @@ def receive(
|
||||
return _untracked_receive(obj_id, remote_transport, local_transport)
|
||||
|
||||
|
||||
def serialize(base: Base, write_transports: List[AbstractTransport] = []) -> str:
|
||||
def serialize(
|
||||
base: Base, write_transports: List[AbstractTransport] | None = None
|
||||
) -> str:
|
||||
"""
|
||||
Serialize a base object. If no write transports are provided,
|
||||
the object will be serialized
|
||||
@@ -67,6 +69,8 @@ def serialize(base: Base, write_transports: List[AbstractTransport] = []) -> str
|
||||
Returns:
|
||||
str -- the serialized object
|
||||
"""
|
||||
if not write_transports:
|
||||
write_transports = []
|
||||
metrics.track(metrics.SDK, custom_props={"name": "Serialize"})
|
||||
return core_serialize(base, write_transports)
|
||||
|
||||
|
||||
@@ -19,8 +19,10 @@ from specklepy.logging.exceptions import SpeckleException
|
||||
class OtherUserResource(CoreResource):
|
||||
"""
|
||||
Provides API access to other users' profiles and activities on the platform.
|
||||
This class enables fetching limited information about users, searching for users by name or email,
|
||||
and accessing user activity logs with appropriate privacy and access control measures in place.
|
||||
This class enables fetching limited information about users,
|
||||
searching for users by name or email,
|
||||
and accessing user activity logs with appropriate privacy
|
||||
and access control measures in place.
|
||||
"""
|
||||
|
||||
def __init__(self, account, basepath, client, server_version) -> None:
|
||||
@@ -63,7 +65,8 @@ class OtherUserResource(CoreResource):
|
||||
limit (int): Maximum number of search results to return.
|
||||
|
||||
Returns:
|
||||
Union[List[LimitedUser], SpeckleException]: A list of users matching the search
|
||||
Union[List[LimitedUser], SpeckleException]:
|
||||
A list of users matching the search
|
||||
query or an exception if the query is too short.
|
||||
"""
|
||||
if len(search_query) < 3:
|
||||
@@ -85,8 +88,8 @@ class OtherUserResource(CoreResource):
|
||||
cursor: Optional[datetime] = None,
|
||||
) -> ActivityCollection:
|
||||
"""
|
||||
Retrieves a collection of activities for a specified user, with optional filters for activity type,
|
||||
time frame, and pagination.
|
||||
Retrieves a collection of activities for a specified user,
|
||||
with optional filters for activity type, time frame, and pagination.
|
||||
|
||||
Args:
|
||||
user_id (str): The ID of the user whose activities are being requested.
|
||||
@@ -97,7 +100,8 @@ class OtherUserResource(CoreResource):
|
||||
cursor (Optional[datetime]): Timestamp for pagination cursor.
|
||||
|
||||
Returns:
|
||||
ActivityCollection: A collection of user activities filtered according to specified criteria.
|
||||
ActivityCollection: A collection of user activities filtered
|
||||
according to specified criteria.
|
||||
"""
|
||||
metrics.track(metrics.SDK, self.account, {"name": "Other User Activity"})
|
||||
return super().activity(user_id, limit, action_type, before, after, cursor)
|
||||
|
||||
@@ -31,7 +31,8 @@ class ServerResource(CoreResource):
|
||||
the server version in the format (major, minor, patch, (tag, build))
|
||||
eg (2, 6, 3) for a stable build and (2, 6, 4, 'alpha', 4711) for alpha
|
||||
"""
|
||||
# not tracking as it will be called along with other mutations / queries as a check
|
||||
# not tracking as it will be called along with other
|
||||
# mutations / queries as a check
|
||||
return super().version()
|
||||
|
||||
def apps(self) -> Dict:
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import contextlib
|
||||
import re
|
||||
from typing import Dict
|
||||
from warnings import warn
|
||||
@@ -49,7 +50,8 @@ class SpeckleClient:
|
||||
client = SpeckleClient(host="app.speckle.systems") # or whatever your host is
|
||||
# client = SpeckleClient(host="localhost:3000", use_ssl=False) or use local server
|
||||
|
||||
# authenticate the client with an account (account has been added in Speckle Manager)
|
||||
# authenticate the client with an account
|
||||
# (account has been added in Speckle Manager)
|
||||
account = get_default_account()
|
||||
client.authenticate_with_account(account)
|
||||
|
||||
@@ -102,7 +104,8 @@ class SpeckleClient:
|
||||
|
||||
self._init_resources()
|
||||
|
||||
# ? Check compatibility with the server - i think we can skip this at this point? save a request
|
||||
# ? Check compatibility with the server
|
||||
# - i think we can skip this at this point? save a request
|
||||
# try:
|
||||
# server_info = self.server.get()
|
||||
# if isinstance(server_info, Exception):
|
||||
@@ -187,9 +190,10 @@ class SpeckleClient:
|
||||
if ex.exception.code == 403:
|
||||
warn(
|
||||
SpeckleWarning(
|
||||
"Possibly invalid token - could not authenticate Speckle Client"
|
||||
f" for server {self.url}"
|
||||
)
|
||||
"Possibly invalid token - could not authenticate "
|
||||
f"Speckle Client for server {self.url}"
|
||||
),
|
||||
stacklevel=2,
|
||||
)
|
||||
else:
|
||||
raise ex
|
||||
@@ -203,10 +207,8 @@ class SpeckleClient:
|
||||
)
|
||||
|
||||
server_version = None
|
||||
try:
|
||||
with contextlib.suppress(Exception):
|
||||
server_version = self.server.version()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
self.other_user = OtherUserResource(
|
||||
account=self.account,
|
||||
@@ -283,7 +285,7 @@ class SpeckleClient:
|
||||
return attr.Resource(
|
||||
account=self.account, basepath=self.url, client=self.httpclient
|
||||
)
|
||||
except AttributeError:
|
||||
except AttributeError as ex:
|
||||
raise SpeckleException(
|
||||
f"Method {name} is not supported by the SpeckleClient class"
|
||||
)
|
||||
) from ex
|
||||
|
||||
@@ -55,7 +55,8 @@ class ServerConfiguration(BaseModel):
|
||||
objectSizeLimitBytes: int
|
||||
|
||||
|
||||
# Keeping this one all Optionals at the minute, because its used both as a deserialization model for GQL and Account Management
|
||||
# Keeping this one all Optionals at the minute,
|
||||
# because its used both as a deserialization model for GQL and Account Management
|
||||
class ServerInfo(BaseModel):
|
||||
name: Optional[str] = None
|
||||
company: Optional[str] = None
|
||||
|
||||
@@ -4,7 +4,10 @@ from typing import List, Optional
|
||||
from deprecated import deprecated
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
FE1_DEPRECATION_REASON = "Stream/Branch/Commit API is now deprecated, Use the new Project/Model/Version API functions in Client}"
|
||||
FE1_DEPRECATION_REASON = (
|
||||
"Stream/Branch/Commit API is now deprecated, "
|
||||
"Use the new Project/Model/Version API functions in Client"
|
||||
)
|
||||
FE1_DEPRECATION_VERSION = "2.20"
|
||||
|
||||
|
||||
|
||||
@@ -70,7 +70,8 @@ def receive(
|
||||
|
||||
serializer = BaseObjectSerializer(read_transport=local_transport)
|
||||
|
||||
# try local transport first. if the parent is there, we assume all the children are there and continue with deserialization using the local transport
|
||||
# try local transport first. if the parent is there, we assume all the children
|
||||
# are there and continue with deserialization using the local transport
|
||||
obj_string = local_transport.get_object(obj_id)
|
||||
if obj_string:
|
||||
return serializer.read_json(obj_string=obj_string)
|
||||
@@ -90,7 +91,7 @@ def receive(
|
||||
return serializer.read_json(obj_string=obj_string)
|
||||
|
||||
|
||||
def serialize(base: Base, write_transports: List[AbstractTransport] = []) -> str:
|
||||
def serialize(base: Base, write_transports: List[AbstractTransport] | None) -> str:
|
||||
"""
|
||||
Serialize a base object. If no write transports are provided,
|
||||
the object will be serialized
|
||||
@@ -104,6 +105,8 @@ def serialize(base: Base, write_transports: List[AbstractTransport] = []) -> str
|
||||
Returns:
|
||||
str -- the serialized object
|
||||
"""
|
||||
if not write_transports:
|
||||
write_transports = []
|
||||
serializer = BaseObjectSerializer(write_transports=write_transports)
|
||||
|
||||
return serializer.write_json(base)[1]
|
||||
|
||||
@@ -18,7 +18,7 @@ from specklepy.transports.sqlite import SQLiteTransport
|
||||
T = TypeVar("T", bound=BaseModel)
|
||||
|
||||
|
||||
class ResourceBase(object):
|
||||
class ResourceBase:
|
||||
def __init__(
|
||||
self,
|
||||
account: Account,
|
||||
@@ -101,7 +101,8 @@ class ResourceBase(object):
|
||||
parse_response: bool = True,
|
||||
) -> Any:
|
||||
"""Executes the GraphQL query"""
|
||||
# This method has quite complex and ambiguous typing, and counter-intuitive error handling
|
||||
# This method has quite complex and ambiguous typing,
|
||||
# and counter-intuitive error handling
|
||||
# We are going to phase it out in favour of `make_request_and_parse_response`
|
||||
try:
|
||||
with self.__lock:
|
||||
|
||||
@@ -36,10 +36,12 @@ class ActiveUserResource(ResourceBase):
|
||||
self.schema = User
|
||||
|
||||
def get(self) -> Optional[User]:
|
||||
"""Gets the currently active user profile (as extracted from the authorization header)
|
||||
"""Gets the currently active user profile
|
||||
(as extracted from the authorization header)
|
||||
|
||||
Returns:
|
||||
User -- the requested user, or none if no authentication token is provided to the Client
|
||||
User -- the requested user, or none if no authentication token
|
||||
is provided to the Client
|
||||
"""
|
||||
QUERY = gql(
|
||||
"""
|
||||
|
||||
@@ -75,14 +75,24 @@ class ModelResource(ResourceBase):
|
||||
) -> ModelWithVersions:
|
||||
QUERY = gql(
|
||||
"""
|
||||
query ModelGetWithVersions($modelId: String!, $projectId: String!, $versionsLimit: Int!, $versionsCursor: String, $versionsFilter: ModelVersionsFilter) {
|
||||
query ModelGetWithVersions(
|
||||
$modelId: String!,
|
||||
$projectId: String!,
|
||||
$versionsLimit: Int!,
|
||||
$versionsCursor: String,
|
||||
$versionsFilter: ModelVersionsFilter
|
||||
) {
|
||||
data:project(id: $projectId) {
|
||||
data:model(id: $modelId) {
|
||||
id
|
||||
name
|
||||
previewUrl
|
||||
updatedAt
|
||||
versions(limit: $versionsLimit, cursor: $versionsCursor, filter: $versionsFilter) {
|
||||
versions(
|
||||
limit: $versionsLimit,
|
||||
cursor: $versionsCursor,
|
||||
filter: $versionsFilter
|
||||
) {
|
||||
items {
|
||||
id
|
||||
referencedObject
|
||||
@@ -147,9 +157,18 @@ class ModelResource(ResourceBase):
|
||||
) -> ResourceCollection[Model]:
|
||||
QUERY = gql(
|
||||
"""
|
||||
query ProjectGetWithModels($projectId: String!, $modelsLimit: Int!, $modelsCursor: String, $modelsFilter: ProjectModelsFilter) {
|
||||
query ProjectGetWithModels(
|
||||
$projectId: String!,
|
||||
$modelsLimit: Int!,
|
||||
$modelsCursor: String,
|
||||
$modelsFilter: ProjectModelsFilter
|
||||
) {
|
||||
data:project(id: $projectId) {
|
||||
data:models(limit: $modelsLimit, cursor: $modelsCursor, filter: $modelsFilter) {
|
||||
data:models(
|
||||
limit: $modelsLimit,
|
||||
cursor: $modelsCursor,
|
||||
filter: $modelsFilter
|
||||
) {
|
||||
items {
|
||||
id
|
||||
name
|
||||
|
||||
@@ -73,7 +73,9 @@ class OtherUserResource(ResourceBase):
|
||||
archived: bool = False,
|
||||
emailOnly: bool = False,
|
||||
) -> UserSearchResultCollection:
|
||||
"""Searches for a user on the server, by name or email. The search query must be at least
|
||||
"""
|
||||
Searches for a user on the server, by name or email.
|
||||
The search query must be at least
|
||||
3 characters long
|
||||
|
||||
Arguments:
|
||||
@@ -88,8 +90,20 @@ class OtherUserResource(ResourceBase):
|
||||
|
||||
QUERY = gql(
|
||||
"""
|
||||
query UserSearch($query: String!, $limit: Int!, $cursor: String, $archived: Boolean, $emailOnly: Boolean) {
|
||||
data:userSearch(query: $query, limit: $limit, cursor: $cursor, archived: $archived, emailOnly: $emailOnly) {
|
||||
query UserSearch(
|
||||
$query: String!,
|
||||
$limit: Int!,
|
||||
$cursor: String,
|
||||
$archived: Boolean,
|
||||
$emailOnly: Boolean
|
||||
) {
|
||||
data:userSearch(
|
||||
query: $query,
|
||||
limit: $limit,
|
||||
cursor: $cursor,
|
||||
archived: $archived,
|
||||
emailOnly: $emailOnly
|
||||
) {
|
||||
cursor
|
||||
items {
|
||||
id
|
||||
|
||||
@@ -36,7 +36,10 @@ class ProjectInviteResource(ResourceBase):
|
||||
) -> ProjectWithTeam:
|
||||
QUERY = gql(
|
||||
"""
|
||||
mutation ProjectInviteCreate($projectId: ID!, $input: ProjectInviteCreateInput!) {
|
||||
mutation ProjectInviteCreate(
|
||||
$projectId: ID!,
|
||||
$input: ProjectInviteCreateInput!
|
||||
) {
|
||||
data:projectMutations {
|
||||
data:invites {
|
||||
data:create(projectId: $projectId, input: $input) {
|
||||
|
||||
@@ -64,7 +64,12 @@ class ProjectResource(ResourceBase):
|
||||
) -> ProjectWithModels:
|
||||
QUERY = gql(
|
||||
"""
|
||||
query ProjectGetWithModels($projectId: String!, $modelsLimit: Int!, $modelsCursor: String, $modelsFilter: ProjectModelsFilter) {
|
||||
query ProjectGetWithModels(
|
||||
$projectId: String!,
|
||||
$modelsLimit: Int!,
|
||||
$modelsCursor: String,
|
||||
$modelsFilter: ProjectModelsFilter
|
||||
) {
|
||||
data:project(id: $projectId) {
|
||||
id
|
||||
name
|
||||
@@ -76,7 +81,11 @@ class ProjectResource(ResourceBase):
|
||||
updatedAt
|
||||
sourceApps
|
||||
workspaceId
|
||||
models(limit: $modelsLimit, cursor: $modelsCursor, filter: $modelsFilter) {
|
||||
models(
|
||||
limit: $modelsLimit,
|
||||
cursor: $modelsCursor,
|
||||
filter: $modelsFilter
|
||||
) {
|
||||
items {
|
||||
id
|
||||
name
|
||||
|
||||
@@ -79,7 +79,8 @@ class ServerResource(ResourceBase):
|
||||
the server version in the format (major, minor, patch, (tag, build))
|
||||
eg (2, 6, 3) for a stable build and (2, 6, 4, 'alpha', 4711) for alpha
|
||||
"""
|
||||
# not tracking as it will be called along with other mutations / queries as a check
|
||||
# not tracking as it will be called along with other mutations / queries
|
||||
# as a check
|
||||
query = gql(
|
||||
"""
|
||||
query Server {
|
||||
|
||||
@@ -159,11 +159,12 @@ class StreamWrapper:
|
||||
try:
|
||||
self.branch_name = project["project"]["model"]["name"]
|
||||
except KeyError as ke:
|
||||
raise SpeckleException("Project model name is not found", ke)
|
||||
raise SpeckleException("Project model name is not found", ke) from ke
|
||||
|
||||
if not self.stream_id:
|
||||
raise SpeckleException(
|
||||
f"Cannot parse {url} into a stream wrapper class - no {key_stream} id found."
|
||||
f"Cannot parse {url} into a stream wrapper class - no {key_stream} ",
|
||||
"id found.",
|
||||
)
|
||||
|
||||
@property
|
||||
@@ -213,7 +214,11 @@ class StreamWrapper:
|
||||
self._client = SpeckleClient(host=self.host, use_ssl=self.use_ssl)
|
||||
|
||||
if self._account.token is None and token is None:
|
||||
warn(f"No local account found for server {self.host}", SpeckleWarning)
|
||||
warn(
|
||||
f"No local account found for server {self.host}",
|
||||
SpeckleWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return self._client
|
||||
|
||||
if self._account.token:
|
||||
@@ -266,14 +271,20 @@ class StreamWrapper:
|
||||
if use_fe2 is False or (use_fe2 is True and not self.model_id):
|
||||
base_url = f"{self.server_url}{key_streams}{self.stream_id}"
|
||||
else: # fe2 is True and model_id available
|
||||
base_url = f"{self.server_url}{key_streams}{self.stream_id}{key_branches}{value_branch}"
|
||||
base_url = (
|
||||
f"{self.server_url}{key_streams}"
|
||||
f"{self.stream_id}{key_branches}{value_branch}"
|
||||
)
|
||||
|
||||
if wrapper_type == "object":
|
||||
return f"{base_url}{key_objects}{self.object_id}"
|
||||
elif wrapper_type == "commit":
|
||||
return f"{base_url}{key_commits}{self.commit_id}"
|
||||
elif wrapper_type == "branch":
|
||||
return f"{self.server_url}{key_streams}{self.stream_id}{key_branches}{value_branch}"
|
||||
return (
|
||||
f"{self.server_url}{key_streams}{self.stream_id}"
|
||||
f"{key_branches}{value_branch}"
|
||||
)
|
||||
elif wrapper_type == "stream":
|
||||
return f"{self.server_url}{key_streams}{self.stream_id}"
|
||||
else:
|
||||
|
||||
@@ -99,7 +99,7 @@ def user_application_data_path() -> Path:
|
||||
except Exception as ex:
|
||||
raise SpeckleException(
|
||||
message="Failed to initialize user application data path.", exception=ex
|
||||
)
|
||||
) from ex
|
||||
|
||||
|
||||
def user_speckle_folder_path() -> Path:
|
||||
|
||||
@@ -86,7 +86,8 @@ def track(
|
||||
|
||||
METRICS_TRACKER.queue.put_nowait(event_params)
|
||||
except Exception as ex:
|
||||
# wrapping this whole thing in a try except as we never want a failure here to annoy users!
|
||||
# wrapping this whole thing in a try except as we never want a failure here
|
||||
# to annoy users!
|
||||
LOG.debug(f"Error queueing metrics request: {str(ex)}")
|
||||
|
||||
|
||||
@@ -106,7 +107,7 @@ class Singleton(type):
|
||||
|
||||
def __call__(cls, *args, **kwargs):
|
||||
if cls not in cls._instances:
|
||||
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
|
||||
cls._instances[cls] = super().__call__(*args, **kwargs)
|
||||
return cls._instances[cls]
|
||||
|
||||
|
||||
|
||||
@@ -223,7 +223,7 @@ def _validate_type(t: Optional[type], value: Any) -> Tuple[bool, Any]:
|
||||
if isinstance(t, ForwardRef):
|
||||
return True, value
|
||||
|
||||
origin = getattr(t, "__origin__")
|
||||
origin = t.__origin__
|
||||
# below is what in nicer for >= py38
|
||||
# origin = get_origin(t)
|
||||
|
||||
@@ -288,7 +288,7 @@ def _validate_type(t: Optional[type], value: Any) -> Tuple[bool, Any]:
|
||||
if len(args) != len(value):
|
||||
return False, value
|
||||
values = []
|
||||
for t_item, v_item in zip(args, value):
|
||||
for t_item, v_item in zip(args, value, strict=True):
|
||||
item_valid, item_value = _validate_type(t_item, v_item)
|
||||
if not item_valid:
|
||||
return False, value
|
||||
@@ -371,7 +371,8 @@ class Base(_RegisteringBase, speckle_type="Base"):
|
||||
if name == "speckle_type":
|
||||
# not sure if we should raise an exception here??
|
||||
# raise SpeckleException(
|
||||
# "Cannot override the `speckle_type`. This is set manually by the class or on deserialisation"
|
||||
# "Cannot override the `speckle_type`."
|
||||
# "This is set manually by the class or on deserialisation"
|
||||
# )
|
||||
return
|
||||
# if value is not None:
|
||||
@@ -399,7 +400,10 @@ class Base(_RegisteringBase, speckle_type="Base"):
|
||||
try:
|
||||
cls._attr_types = get_type_hints(cls)
|
||||
except Exception as e:
|
||||
warn(f"Could not update forward refs for class {cls.__name__}: {e}")
|
||||
warn(
|
||||
f"Could not update forward refs for class {cls.__name__}: {e}",
|
||||
stacklevel=2,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def validate_prop_name(cls, name: str) -> None:
|
||||
@@ -464,7 +468,8 @@ class Base(_RegisteringBase, speckle_type="Base"):
|
||||
|
||||
# @units.setter
|
||||
# def units(self, value: Union[str, Units, None]):
|
||||
# """While this property accepts any string value, geometry expects units to be specific strings (see Units enum)"""
|
||||
# """While this property accepts any string value,
|
||||
# geometry expects units to be specific strings (see Units enum)"""
|
||||
# if isinstance(value, str) or value is None:
|
||||
# self._units = value
|
||||
# elif isinstance(value, Units):
|
||||
|
||||
@@ -23,7 +23,10 @@ class Point(Base, IHasUnits, speckle_type="Objects.Geometry.Point"):
|
||||
z: float
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"{self.__class__.__name__}(x: {self.x}, y: {self.y}, z: {self.z}, units: {self.units})"
|
||||
return (
|
||||
f"{self.__class__.__name__}"
|
||||
f"(x: {self.x}, y: {self.y}, z: {self.z}, units: {self.units})"
|
||||
)
|
||||
|
||||
def to_list(self) -> List[float]:
|
||||
return [self.x, self.y, self.z]
|
||||
|
||||
@@ -67,7 +67,7 @@ class IHasArea(metaclass=ABCMeta):
|
||||
|
||||
@area.setter
|
||||
def area(self, value: float):
|
||||
if not isinstance(value, (int, float)):
|
||||
if not isinstance(value, int | float):
|
||||
raise ValueError(f"Area must be a number, got {type(value)}")
|
||||
self._area = float(value)
|
||||
|
||||
@@ -83,7 +83,7 @@ class IHasVolume(metaclass=ABCMeta):
|
||||
|
||||
@volume.setter
|
||||
def volume(self, value: float):
|
||||
if not isinstance(value, (int, float)):
|
||||
if not isinstance(value, int | float):
|
||||
raise ValueError(f"Volume must be a number, got {type(value)}")
|
||||
self._volume = float(value)
|
||||
|
||||
|
||||
@@ -12,18 +12,25 @@ class Collection(
|
||||
detachable={"elements"},
|
||||
):
|
||||
"""
|
||||
A simple container for organising objects within a model and preserving object hierarchy.
|
||||
A simple container for organising objects within a model
|
||||
and preserving object hierarchy.
|
||||
|
||||
A container is defined by a human-readable name a unique applicationId and its list of contained elements.
|
||||
The elements can include an unrestricted number of Base objects including additional nested Collections.
|
||||
A container is defined by a human-readable name a unique applicationId and
|
||||
its list of contained elements.
|
||||
The elements can include an unrestricted number of Base objects including
|
||||
additional nested Collections.
|
||||
|
||||
Note:
|
||||
A Collection can be for example a Layer in Rhino/AutoCad, a collection in Blender, or a Category in Revit.
|
||||
The location of each collection in the hierarchy of collections in a commit will be retrieved through commit traversal.
|
||||
A Collection can be for example a Layer in Rhino/AutoCad,
|
||||
a collection in Blender, or a Category in Revit.
|
||||
The location of each collection in the hierarchy of collections in a commit
|
||||
will be retrieved through commit traversal.
|
||||
|
||||
Attributes:
|
||||
name: The human-readable name of the Collection. This name is not necessarily unique within a commit. Set the applicationId for a unique identifier.
|
||||
elements: The elements contained in this Collection. This may include additional nested Collections
|
||||
name: The human-readable name of the Collection. This name is not necessarily
|
||||
unique within a commit. Set the applicationId for a unique identifier.
|
||||
elements: The elements contained in this Collection.
|
||||
This may include additional nested Collections
|
||||
"""
|
||||
|
||||
name: str
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from dataclasses import dataclass, field
|
||||
from dataclasses import dataclass
|
||||
from typing import List, Optional
|
||||
|
||||
from specklepy.objects.base import Base
|
||||
|
||||
@@ -148,7 +148,7 @@ cube_mesh = Mesh(
|
||||
volume=0.0,
|
||||
)
|
||||
|
||||
print(f"\nMesh Details:")
|
||||
print("\nMesh Details:")
|
||||
print(f"Number of vertices: {cube_mesh.vertices_count}")
|
||||
print(f"Number of texture coordinates: {cube_mesh.texture_coordinates_count}")
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ from warnings import warn
|
||||
from stringcase import pascalcase
|
||||
|
||||
from specklepy.logging.exceptions import SpeckleException, SpeckleInvalidUnitException
|
||||
from specklepy.objects.units import Units
|
||||
from specklepy.objects_v2.units import Units
|
||||
from specklepy.transports.memory import MemoryTransport
|
||||
|
||||
PRIMITIVES = (int, float, str, bool)
|
||||
@@ -225,7 +225,7 @@ def _validate_type(t: Optional[type], value: Any) -> Tuple[bool, Any]:
|
||||
if isinstance(t, ForwardRef):
|
||||
return True, value
|
||||
|
||||
origin = getattr(t, "__origin__")
|
||||
origin = t.__origin__
|
||||
# below is what in nicer for >= py38
|
||||
# origin = get_origin(t)
|
||||
|
||||
@@ -290,7 +290,7 @@ def _validate_type(t: Optional[type], value: Any) -> Tuple[bool, Any]:
|
||||
if len(args) != len(value):
|
||||
return False, value
|
||||
values = []
|
||||
for t_item, v_item in zip(args, value):
|
||||
for t_item, v_item in zip(args, value, strict=True):
|
||||
item_valid, item_value = _validate_type(t_item, v_item)
|
||||
if not item_valid:
|
||||
return False, value
|
||||
@@ -387,7 +387,8 @@ class Base(_RegisteringBase, speckle_type="Base"):
|
||||
if name == "speckle_type":
|
||||
# not sure if we should raise an exception here??
|
||||
# raise SpeckleException(
|
||||
# "Cannot override the `speckle_type`. This is set manually by the class or on deserialisation"
|
||||
# "Cannot override the `speckle_type`."
|
||||
# "This is set manually by the class or on deserialisation"
|
||||
# )
|
||||
return
|
||||
# if value is not None:
|
||||
@@ -415,7 +416,10 @@ class Base(_RegisteringBase, speckle_type="Base"):
|
||||
try:
|
||||
cls._attr_types = get_type_hints(cls)
|
||||
except Exception as e:
|
||||
warn(f"Could not update forward refs for class {cls.__name__}: {e}")
|
||||
warn(
|
||||
f"Could not update forward refs for class {cls.__name__}: {e}",
|
||||
stacklevel=2,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def validate_prop_name(cls, name: str) -> None:
|
||||
@@ -480,7 +484,10 @@ class Base(_RegisteringBase, speckle_type="Base"):
|
||||
|
||||
@units.setter
|
||||
def units(self, value: Union[str, Units, None]):
|
||||
"""While this property accepts any string value, geometry expects units to be specific strings (see Units enum)"""
|
||||
"""
|
||||
While this property accepts any string value,
|
||||
geometry expects units to be specific strings (see Units enum)
|
||||
"""
|
||||
if isinstance(value, str) or value is None:
|
||||
self._units = value
|
||||
elif isinstance(value, Units):
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
from enum import Enum
|
||||
from typing import Any, List, Optional
|
||||
|
||||
from specklepy.objects.base import Base
|
||||
from specklepy.objects.encoding import CurveArray, CurveTypeEncoding, ObjectArray
|
||||
from specklepy.objects.primitive import Interval
|
||||
from specklepy.objects.units import get_encoding_from_units, get_units_from_encoding
|
||||
from specklepy.objects_v2.base import Base
|
||||
from specklepy.objects_v2.encoding import CurveArray, CurveTypeEncoding, ObjectArray
|
||||
from specklepy.objects_v2.primitive import Interval
|
||||
from specklepy.objects_v2.units import get_encoding_from_units, get_units_from_encoding
|
||||
|
||||
GEOMETRY = "Objects.Geometry."
|
||||
|
||||
@@ -918,10 +918,12 @@ class Brep(
|
||||
|
||||
self.Vertices = vertices
|
||||
|
||||
# TODO: can this be consistent with loops, edges, faces, curves, etc and prepend with the chunk list? needs to happen in sharp first
|
||||
# TODO: can this be consistent with loops, edges, faces, curves,
|
||||
# etc and prepend with the chunk list? needs to happen in sharp first
|
||||
@property
|
||||
def TrimsValue(self) -> List[float]:
|
||||
# return None if self.Trims is None else ObjectArray.from_objects(self.Trims).data
|
||||
# return None if self.Trims is None else
|
||||
# ObjectArray.from_objects(self.Trims).data
|
||||
if not self.Trims:
|
||||
return
|
||||
value = []
|
||||
|
||||
@@ -57,9 +57,7 @@ class CommitObjectBuilder(ABC, Generic[T]):
|
||||
if parent_id == ROOT:
|
||||
parent = root_commit_object
|
||||
else:
|
||||
parent = (
|
||||
self.converted[parent_id] if parent_id in self.converted else None
|
||||
)
|
||||
parent = self.converted.get(parent_id, None)
|
||||
|
||||
if not parent:
|
||||
continue
|
||||
@@ -73,13 +71,15 @@ class CommitObjectBuilder(ABC, Generic[T]):
|
||||
elements.append(current)
|
||||
return
|
||||
except Exception as ex:
|
||||
# A parent was found, but it was invalid (Likely because of a type mismatch on a `elements` property)
|
||||
# A parent was found, but it was invalid
|
||||
# (Likely because of a type mismatch on a `elements` property)
|
||||
print(
|
||||
f"Failed to add object {type(current)} to a converted parent; {ex}"
|
||||
)
|
||||
|
||||
raise Exception(
|
||||
f"Could not find a valid parent for object of type {type(current)}. Checked {len(parents)} potential parent, and non were converted!"
|
||||
f"Could not find a valid parent for object of type {type(current)}."
|
||||
f"Checked {len(parents)} potential parent, and non were converted!"
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -57,12 +57,16 @@ class GraphTraversal:
|
||||
for child_prop in members_to_traverse:
|
||||
try:
|
||||
if child_prop in {"speckle_type", "units", "applicationId"}:
|
||||
continue # debug: to avoid noisy exceptions, explicitly avoid checking ones we know will fail, this is not exhaustive
|
||||
# debug: to avoid noisy exceptions,
|
||||
# explicitly avoid checking ones we know will fail,
|
||||
# this is not exhaustive
|
||||
continue
|
||||
if getattr(current, child_prop, None):
|
||||
value = current[child_prop]
|
||||
self._traverse_member_to_stack(stack, value, child_prop, head)
|
||||
except KeyError:
|
||||
# Unset application ids, and class variables like SpeckleType will throw when __getitem__ is called
|
||||
# Unset application ids, and class variables like SpeckleType will
|
||||
# throw when __getitem__ is called
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
@@ -118,7 +122,4 @@ class TraversalRule:
|
||||
return set(self._members_to_traverse(o))
|
||||
|
||||
def does_rule_hold(self, o: Base) -> bool:
|
||||
for condition in self._conditions:
|
||||
if condition(o):
|
||||
return True
|
||||
return False
|
||||
return any(condition(o) for condition in self._conditions)
|
||||
|
||||
@@ -30,6 +30,7 @@ def safe_json_loads(obj: str, obj_id=None) -> Any:
|
||||
f"Failed to deserialise object (id: {obj_id}). This is likely a ujson big"
|
||||
f" int error - falling back to json. \nError: {err}",
|
||||
SpeckleWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return json.loads(obj)
|
||||
|
||||
@@ -140,7 +141,8 @@ class BaseObjectSerializer:
|
||||
object_builder[prop] = value
|
||||
continue
|
||||
|
||||
# NOTE: for dynamic props, this won't be re-serialised as an enum but as an int
|
||||
# NOTE: for dynamic props, this won't be re-serialised
|
||||
# as an enum but as an int
|
||||
if isinstance(value, Enum):
|
||||
object_builder[prop] = value.value
|
||||
continue
|
||||
@@ -222,7 +224,7 @@ class BaseObjectSerializer:
|
||||
if isinstance(obj, Enum):
|
||||
return obj.value
|
||||
|
||||
elif isinstance(obj, (list, tuple, set)):
|
||||
elif isinstance(obj, list | tuple | set):
|
||||
if not detach:
|
||||
return [self.traverse_value(o) for o in obj]
|
||||
|
||||
@@ -257,6 +259,7 @@ class BaseObjectSerializer:
|
||||
f"Failed to handle {type(obj)} in"
|
||||
" `BaseObjectSerializer.traverse_value`",
|
||||
SpeckleWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
|
||||
return str(obj)
|
||||
@@ -374,6 +377,7 @@ class BaseObjectSerializer:
|
||||
f"Could not find the referenced child object of id `{ref_id}`"
|
||||
f" in the given read transport: {self.read_transport.name}",
|
||||
SpeckleWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
base.__setattr__(prop, self.handle_value(value))
|
||||
|
||||
@@ -437,6 +441,7 @@ class BaseObjectSerializer:
|
||||
f"Could not find the referenced child object of id `{ref_id}` in the"
|
||||
f" given read transport: {self.read_transport.name}",
|
||||
SpeckleWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return obj
|
||||
|
||||
|
||||
@@ -27,8 +27,8 @@ class MemoryTransport(AbstractTransport):
|
||||
) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def get_object(self, id: str) -> str or None:
|
||||
return self.objects[id] if id in self.objects else None
|
||||
def get_object(self, id: str) -> str | None:
|
||||
return self.objects.get(id, None)
|
||||
|
||||
def has_objects(self, id_list: List[str]) -> Dict[str, bool]:
|
||||
return {id: (id in self.objects) for id in id_list}
|
||||
|
||||
@@ -11,7 +11,7 @@ from specklepy.logging.exceptions import SpeckleException
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class BatchSender(object):
|
||||
class BatchSender:
|
||||
def __init__(
|
||||
self,
|
||||
server_url,
|
||||
@@ -123,8 +123,14 @@ class BatchSender(object):
|
||||
upload_data = "[" + ",".join(new_objects) + "]"
|
||||
upload_data_gzip = gzip.compress(upload_data.encode())
|
||||
LOG.info(
|
||||
"Uploading batch of %s objects (%s new): (size: %s, compressed size: %s)"
|
||||
% (len(batch), len(new_objects), len(upload_data), len(upload_data_gzip))
|
||||
"Uploading batch of {batch_size} objects {new_object_count}: ",
|
||||
"(size: {upload_size}, compressed size: {upload_data_size})",
|
||||
{
|
||||
"batch_size": len(batch),
|
||||
"new_object_count": len(new_objects),
|
||||
"upload_size": len(upload_data),
|
||||
"upload_data_size": len(upload_data_gzip),
|
||||
},
|
||||
)
|
||||
|
||||
try:
|
||||
|
||||
@@ -74,7 +74,8 @@ class ServerTransport(AbstractTransport):
|
||||
SpeckleWarning(
|
||||
"Unauthenticated Speckle Client provided to Server Transport"
|
||||
f" for {url}. Receiving from private streams will fail."
|
||||
)
|
||||
),
|
||||
stacklevel=2,
|
||||
)
|
||||
else:
|
||||
self.account = client.account
|
||||
|
||||
@@ -39,8 +39,7 @@ class SQLiteTransport(AbstractTransport):
|
||||
f"SQLiteTransport could not initialise {self.scope}.db at"
|
||||
f" {self._base_path}. Either provide a different `base_path` or use an"
|
||||
" alternative transport.",
|
||||
ex,
|
||||
)
|
||||
) from ex
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"SQLiteTransport(app: '{self.app_name}', scope: '{self.scope}')"
|
||||
@@ -105,10 +104,9 @@ class SQLiteTransport(AbstractTransport):
|
||||
raise SpeckleException(
|
||||
"Could not save the batch of objects to the local db. Inner exception:"
|
||||
f" {ex}",
|
||||
ex,
|
||||
)
|
||||
) from ex
|
||||
|
||||
def get_object(self, id: str) -> str or None:
|
||||
def get_object(self, id: str) -> str | None:
|
||||
self.__check_connection()
|
||||
with closing(self.__connection.cursor()) as c:
|
||||
row = c.execute(
|
||||
|
||||
@@ -44,7 +44,8 @@ class TestActiveUserResource:
|
||||
|
||||
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
|
||||
# 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)
|
||||
)
|
||||
|
||||
@@ -32,8 +32,8 @@ class TestOtherUser:
|
||||
assert isinstance(fetched_user, LimitedUser)
|
||||
assert fetched_user.name == second_user_dict["name"]
|
||||
# changed in the server, now you cannot get emails of other users
|
||||
# not checking this, since the first user could or could not be an admin on the server
|
||||
# admins can get emails of others, regular users can't
|
||||
# not checking this, since the first user could or could not be an admin
|
||||
# on the server, admins can get emails of others, regular users can't
|
||||
# assert fetched_user.email == None
|
||||
|
||||
second_user_dict["id"] = fetched_user.id
|
||||
|
||||
@@ -35,8 +35,8 @@ class TestUser:
|
||||
assert isinstance(fetched_user, User)
|
||||
assert fetched_user.name == second_user_dict["name"]
|
||||
# changed in the server, now you cannot get emails of other users
|
||||
# not checking this, since the first user could or could not be an admin on the server
|
||||
# admins can get emails of others, regular users can't
|
||||
# not checking this, since the first user could or could not be an admin
|
||||
# on the server, admins can get emails of others, regular users can't
|
||||
# assert fetched_user.email == None
|
||||
|
||||
second_user_dict["id"] = fetched_user.id
|
||||
|
||||
Reference in New Issue
Block a user