Merge pull request #241 from specklesystems/speckle_type_sync_with_core

speckle type sync with core
This commit is contained in:
Gergő Jedlicska
2022-12-21 11:59:39 +01:00
committed by GitHub
64 changed files with 1064 additions and 598 deletions
+8 -7
View File
@@ -1,12 +1,13 @@
from typing import List
from specklepy.objects import Base
from specklepy.api import operations
from specklepy.transports.sqlite import SQLiteTransport
import os
import random
import string
import time
from pathlib import Path
import os
import string
import random
from typing import List
from specklepy.api import operations
from specklepy.objects import Base
from specklepy.transports.sqlite import SQLiteTransport
class Sub(Base):
+4 -3
View File
@@ -1,9 +1,10 @@
import random
import string
from typing import List
from specklepy.api import operations
from specklepy.api.wrapper import StreamWrapper
from specklepy.objects import Base
from specklepy.api import operations
import string
import random
class Sub(Base):
+3 -2
View File
@@ -1,10 +1,11 @@
"""This is an example showcasing the usage of speckle `Base` class."""
# the speckle.objects module exposes all speckle provided classes
from specklepy.objects import Base
from specklepy.api import operations
from devtools import debug
from specklepy.api import operations
from specklepy.objects import Base
class ExampleSub(Base):
"""
+3
View File
@@ -54,3 +54,6 @@ target-version = ["py37", "py38", "py39", "py310"]
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
[tool.isort]
profile = "black"
+18 -20
View File
@@ -1,30 +1,28 @@
import re
from warnings import warn
from deprecated import deprecated
from specklepy.api.credentials import Account, get_account_from_token
from specklepy.logging import metrics
from specklepy.logging.exceptions import (
SpeckleException,
SpeckleWarning,
)
from typing import Dict
from warnings import warn
from specklepy.api import resources
from specklepy.api.resources import (
branch,
commit,
stream,
object,
server,
user,
subscriptions,
other_user,
active_user
)
from deprecated import deprecated
from gql import Client
from gql.transport.requests import RequestsHTTPTransport
from gql.transport.websockets import WebsocketsTransport
from specklepy.api import resources
from specklepy.api.credentials import Account, get_account_from_token
from specklepy.api.resources import (
active_user,
branch,
commit,
object,
other_user,
server,
stream,
subscriptions,
user,
)
from specklepy.logging import metrics
from specklepy.logging.exceptions import SpeckleException, SpeckleWarning
class SpeckleClient:
"""
+8 -6
View File
@@ -1,11 +1,13 @@
import os
from pydantic import BaseModel, Field # pylint: disable=no-name-in-module
from typing import List, Optional
from specklepy.logging import metrics
from specklepy.api.models import ServerInfo
from specklepy.transports.sqlite import SQLiteTransport
from specklepy.logging.exceptions import SpeckleException
from pydantic import BaseModel, Field # pylint: disable=no-name-in-module
from specklepy import paths
from specklepy.api.models import ServerInfo
from specklepy.logging import metrics
from specklepy.logging.exceptions import SpeckleException
from specklepy.transports.sqlite import SQLiteTransport
class UserInfo(BaseModel):
@@ -64,7 +66,7 @@ def get_local_accounts(base_path: Optional[str] = None) -> List[Account]:
json_acct_files.extend(
file for file in os.listdir(json_path) if file.endswith(".json")
)
except Exception:
# cannot find or get the json account paths
pass
+1 -1
View File
@@ -1,5 +1,5 @@
from enum import Enum
from dataclasses import dataclass
from enum import Enum
from unicodedata import name
+9 -10
View File
@@ -1,7 +1,6 @@
from datetime import datetime
from typing import List, Optional
from pydantic import BaseModel, Field
@@ -60,20 +59,20 @@ class Branches(BaseModel):
class Stream(BaseModel):
id: Optional[str] = None
id: Optional[str] = None
name: Optional[str]
role: Optional[str] = None
isPublic: Optional[bool] = None
description: Optional[str] = None
createdAt: Optional[datetime] = None
updatedAt: Optional[datetime] = None
createdAt: Optional[datetime] = None
updatedAt: Optional[datetime] = None
collaborators: List[Collaborator] = Field(default_factory=list)
branches: Optional[Branches] = None
commit: Optional[Commit] = None
object: Optional[Object] = None
commentCount: Optional[int] = None
favoritedDate: Optional[datetime] = None
favoritesCount: Optional[int] = None
branches: Optional[Branches] = None
commit: Optional[Commit] = None
object: Optional[Object] = None
commentCount: Optional[int] = None
favoritedDate: Optional[datetime] = None
favoritesCount: Optional[int] = None
def __repr__(self):
return f"Stream( id: {self.id}, name: {self.name}, description: {self.description}, isPublic: {self.isPublic})"
+4 -3
View File
@@ -1,10 +1,11 @@
from typing import List, Optional
from specklepy.logging import metrics
from specklepy.objects.base import Base
from specklepy.transports.sqlite import SQLiteTransport
from specklepy.logging.exceptions import SpeckleException
from specklepy.transports.abstract_transport import AbstractTransport
from specklepy.objects.base import Base
from specklepy.serialization.base_object_serializer import BaseObjectSerializer
from specklepy.transports.abstract_transport import AbstractTransport
from specklepy.transports.sqlite import SQLiteTransport
def send(
+5 -3
View File
@@ -1,15 +1,17 @@
from graphql import DocumentNode
from specklepy.api.credentials import Account
from specklepy.transports.sqlite import SQLiteTransport
from typing import Any, Dict, List, Optional, Tuple, Type, Union
from gql.client import Client
from gql.transport.exceptions import TransportQueryError
from graphql import DocumentNode
from specklepy.api.credentials import Account
from specklepy.logging.exceptions import (
GraphQLException,
SpeckleException,
UnsupportedException,
)
from specklepy.serialization.base_object_serializer import BaseObjectSerializer
from specklepy.transports.sqlite import SQLiteTransport
class ResourceBase(object):
+1 -3
View File
@@ -1,9 +1,7 @@
from pathlib import Path
import sys
import pkgutil
import sys
from importlib import import_module
for (_, name, _) in pkgutil.iter_modules(__path__):
imported_module = import_module("." + name, package=__name__)
+5 -4
View File
@@ -1,11 +1,12 @@
from typing import List, Optional
from datetime import datetime, timezone
from typing import List, Optional
from gql import gql
from specklepy.api.models import ActivityCollection, PendingStreamCollaborator, User
from specklepy.api.resource import ResourceBase
from specklepy.logging import metrics
from specklepy.logging.exceptions import SpeckleException
from specklepy.api.resource import ResourceBase
from specklepy.api.models import ActivityCollection, PendingStreamCollaborator, User
NAME = "active_user"
+2 -1
View File
@@ -1,6 +1,7 @@
from gql import gql
from specklepy.api.resource import ResourceBase
from specklepy.api.models import Branch
from specklepy.api.resource import ResourceBase
from specklepy.logging import metrics
NAME = "branch"
+6 -5
View File
@@ -1,9 +1,10 @@
from typing import Optional, List
from gql import gql
from specklepy.api.resource import ResourceBase
from specklepy.api.models import Commit
from specklepy.logging import metrics
from typing import List, Optional
from gql import gql
from specklepy.api.models import Commit
from specklepy.api.resource import ResourceBase
from specklepy.logging import metrics
NAME = "commit"
+2
View File
@@ -1,5 +1,7 @@
from typing import Dict, List
from gql import gql
from specklepy.api.resource import ResourceBase
from specklepy.objects.base import Base
+5 -6
View File
@@ -1,13 +1,12 @@
from typing import List, Optional, Union
from datetime import datetime, timezone
from typing import List, Optional, Union
from gql import gql
from specklepy.api.models import ActivityCollection, LimitedUser
from specklepy.api.resource import ResourceBase
from specklepy.logging import metrics
from specklepy.logging.exceptions import SpeckleException
from specklepy.api.resource import ResourceBase
from specklepy.api.models import (
ActivityCollection,
LimitedUser,
)
NAME = "other_user"
+2 -1
View File
@@ -1,12 +1,13 @@
import re
from typing import Any, Dict, List, Tuple
from gql import gql
from specklepy.api.models import ServerInfo
from specklepy.api.resource import ResourceBase
from specklepy.logging import metrics
from specklepy.logging.exceptions import GraphQLException
NAME = "server"
+4 -3
View File
@@ -1,12 +1,13 @@
from datetime import datetime, timezone
from typing import List, Optional
from deprecated import deprecated
from gql import gql
from specklepy.logging import metrics
from specklepy.api.models import ActivityCollection, PendingStreamCollaborator, Stream
from specklepy.api.resource import ResourceBase
from specklepy.logging.exceptions import UnsupportedException, SpeckleException
from specklepy.logging import metrics
from specklepy.logging.exceptions import SpeckleException, UnsupportedException
NAME = "stream"
+3 -1
View File
@@ -1,7 +1,9 @@
from typing import Callable, Dict, List, Union
from functools import wraps
from typing import Callable, Dict, List, Union
from gql import gql
from graphql import DocumentNode
from specklepy.api.resource import ResourceBase
from specklepy.api.resources.stream import Stream
from specklepy.logging.exceptions import SpeckleException
+6 -5
View File
@@ -1,12 +1,13 @@
from typing import List, Optional, Union
from datetime import datetime, timezone
from typing import List, Optional, Union
from deprecated import deprecated
from gql import gql
from specklepy.api.models import ActivityCollection, PendingStreamCollaborator, User
from specklepy.api.resource import ResourceBase
from specklepy.logging import metrics
from specklepy.logging.exceptions import SpeckleException
from specklepy.api.resource import ResourceBase
from specklepy.api.models import ActivityCollection, PendingStreamCollaborator, User
from deprecated import deprecated
NAME = "user"
+4 -3
View File
@@ -1,14 +1,15 @@
from urllib.parse import unquote, urlparse
from warnings import warn
from urllib.parse import urlparse, unquote
from specklepy.api.client import SpeckleClient
from specklepy.api.credentials import (
Account,
get_account_from_token,
get_local_accounts,
)
from specklepy.logging import metrics
from specklepy.api.client import SpeckleClient
from specklepy.transports.server.server import ServerTransport
from specklepy.logging.exceptions import SpeckleException, SpeckleWarning
from specklepy.transports.server.server import ServerTransport
class StreamWrapper:
+9 -9
View File
@@ -1,14 +1,14 @@
import sys
import queue
import hashlib
import getpass
import logging
from typing import Optional
import requests
import threading
import platform
import contextlib
import getpass
import hashlib
import logging
import platform
import queue
import sys
import threading
from typing import Optional
import requests
"""
Anonymous telemetry to help us understand how to make a better Speckle.
+2 -1
View File
@@ -1,5 +1,6 @@
"""Builtin Speckle object kit."""
from specklepy.objects import encoding, geometry, other, primitive, structural, units
from specklepy.objects.base import Base
__all__ = ["Base"]
__all__ = ["Base", "encoding", "geometry", "other", "units", "structural", "primitive"]
+147 -58
View File
@@ -1,21 +1,22 @@
import contextlib
from enum import Enum
from inspect import isclass
from typing import (
Any,
ClassVar,
Dict,
List,
Optional,
Union,
Set,
Tuple,
Type,
Union,
get_type_hints,
)
import contextlib
from enum import EnumMeta
from warnings import warn
from specklepy.logging.exceptions import SpeckleException, SpeckleInvalidUnitException
from specklepy.objects.units import get_units_from_string, Units
from specklepy.logging.exceptions import SpeckleException
from specklepy.objects.units import Units, get_units_from_string
from specklepy.transports.memory import MemoryTransport
PRIMITIVES = (int, float, str, bool)
@@ -90,7 +91,8 @@ class _RegisteringBase:
"""
speckle_type: ClassVar[str]
_type_registry: ClassVar[Dict[str, "Base"]] = {}
_speckle_type_override: ClassVar[Optional[str]] = None
_type_registry: ClassVar[Dict[str, Type["Base"]]] = {}
_attr_types: ClassVar[Dict[str, Type]] = {}
# dict of chunkable props and their max chunk size
_chunkable: Dict[str, int] = {}
@@ -98,22 +100,40 @@ class _RegisteringBase:
_detachable: Set[str] = set() # list of defined detachable props
_serialize_ignore: Set[str] = set()
class Config:
validate_assignment = True
@classmethod
def get_registered_type(
cls, speckle_type: str
) -> Union["Base", Type["Base"], None]:
def get_registered_type(cls, speckle_type: str) -> Optional[Type["Base"]]:
"""Get the registered type from the protected mapping via the `speckle_type`"""
return cls._type_registry.get(speckle_type, None)
@classmethod
def _determine_speckle_type(cls) -> str:
"""
This method brings the speckle_type construction in par with peckle-sharp/Core.
The implementation differs, because in Core the basis of the speckle_type if
type.FullName, which includes the dotnet namespace name too.
Copying that behavior is hard in python, where the concept of namespaces
means something entirely different.
So we enabled a speckle_type override mechanism, that enables
"""
base_name = "Base"
if cls.__name__ == base_name:
return base_name
bases = [
b._speckle_type_override if b._speckle_type_override else b.__name__
for b in reversed(cls.mro())
if issubclass(b, Base) and b.__name__ != base_name
]
return ":".join(bases)
def __init_subclass__(
cls,
speckle_type: str = None,
chunkable: Dict[str, int] = None,
detachable: Set[str] = None,
serialize_ignore: Set[str] = None,
speckle_type: Optional[str] = None,
chunkable: Optional[Dict[str, int]] = None,
detachable: Optional[Set[str]] = None,
serialize_ignore: Optional[Set[str]] = None,
**kwargs: Dict[str, Any],
):
"""
@@ -123,13 +143,14 @@ class _RegisteringBase:
initialization. This is reused to register each subclassing type into a class
level dictionary.
"""
if speckle_type in cls._type_registry:
cls._speckle_type_override = speckle_type
cls.speckle_type = cls._determine_speckle_type()
if cls.speckle_type in cls._type_registry:
raise ValueError(
f"The speckle_type: {speckle_type} is already registered for type: "
f"{cls._type_registry[speckle_type].__name__}. "
f"{cls._type_registry[cls.speckle_type].__name__}. "
f"Please choose a different type name."
)
cls.speckle_type = speckle_type or cls.__name__
cls._type_registry[cls.speckle_type] = cls # type: ignore
try:
cls._attr_types = get_type_hints(cls)
@@ -145,6 +166,102 @@ class _RegisteringBase:
super().__init_subclass__(**kwargs)
# T = TypeVar("T")
# how i wish the code below would be correct, but we're also parsing into floats
# and converting into strings if the original type is string, but the value isn't
# def _validate_type(t: type, value: T) -> Tuple[bool, T]:
def _validate_type(t: Optional[type], value: Any) -> Tuple[bool, Any]:
# this should be reworked. Its only ok to return null for Optionals...
# if t is None and value is None:
if value is None:
return True, value
# after fixing the None t above, this should be
# if t is Any:
# if t is None:
if t is None or t is Any:
return True, value
if isclass(t) and issubclass(t, Enum):
if isinstance(value, t):
return True, value
if value in t._value2member_map_:
return True, t(value)
if getattr(t, "__module__", None) == "typing":
origin = getattr(t, "__origin__")
# below is what in nicer for >= py38
# origin = get_origin(t)
# recursive validation for Unions on both types preferring the fist type
if origin is Union:
t_1, t_2 = t.__args__ # type: ignore
# below is what in nicer for >= py38
# t_1, t_2 = get_args(t)
t_1_success, t_1_value = _validate_type(t_1, value)
if t_1_success:
return True, t_1_value
return _validate_type(t_2, value)
if origin is dict:
if not isinstance(value, dict):
return False, value
if value == {}:
return True, value
t_key, t_value = t.__args__ # type: ignore
# we're only checking the first item, but the for loop and return after
# evaluating the first item is the fastest way
for dict_key, dict_value in value.items():
valid_key, _ = _validate_type(t_key, dict_key)
valid_value, _ = _validate_type(t_value, dict_value)
if valid_key and valid_value:
return True, value
return False, value
if origin is list:
if not isinstance(value, list):
return False, value
if value == []:
return True, value
t_items = t.__args__[0] # type: ignore
first_item_valid, _ = _validate_type(t_items, value[0])
if first_item_valid:
return True, value
return False, value
if origin is tuple:
if not isinstance(value, tuple):
return False, value
args = t.__args__ # type: ignore
# we're not checking for empty tuple, cause tuple lengths must match
if len(args) != len(value):
return False, value
values = []
for t_item, v_item in zip(args, value):
item_valid, item_value = _validate_type(t_item, v_item)
if not item_valid:
return False, value
values.append(item_value)
return True, tuple(values)
if isinstance(value, t):
return True, value
with contextlib.suppress(ValueError):
if t is float and value is not None:
return True, float(value)
# TODO: dafuq, i had to add this not list check
# but it would also fail for objects and other complex values
if t is str and value and not isinstance(value, list):
return True, str(value)
return False, value
class Base(_RegisteringBase):
id: Union[str, None] = None
totalChildrenCount: Union[int, None] = None
@@ -242,55 +359,27 @@ class Base(_RegisteringBase):
"Invalid Name: Base member names cannot contain characters '.' or '/'",
)
def _type_check(self, name: str, value: Any):
def _type_check(self, name: str, value: Any) -> Any:
"""
Lightweight type checking of values before setting them
NOTE: Does not check subscripted types within generics as the performance hit of checking
each item within a given collection isn't worth it. Eg if you have a type Dict[str, float],
NOTE: Does not check subscripted types within generics as the performance hit
of checking each item within a given collection isn't worth it.
Eg if you have a type Dict[str, float],
we will only check if the value you're trying to set is a dict.
"""
types = getattr(self, "_attr_types", {})
t = types.get(name, None)
if t is None or t is Any:
return value
valid, checked_value = _validate_type(t, value)
if value is None:
return None
if isinstance(t, EnumMeta) and (value in t._value2member_map_):
return t(value)
if t.__module__ == "typing":
origin = getattr(t, "__origin__")
t = (
tuple(getattr(sub_t, "__origin__", sub_t) for sub_t in t.__args__)
if origin is Union
else origin
)
if not isinstance(t, (type, tuple)):
warn(
f"Unrecognised type '{t}' provided for attribute '{name}'. Type will not been validated."
)
return value
if isinstance(value, t):
return value
# to be friendly, we'll parse ints and strs into floats, but not the other way around
# (to avoid unexpected rounding)
if isinstance(t, tuple):
t = t[0]
with contextlib.suppress(ValueError):
if t is float:
return float(value)
if t is str and value:
return str(value)
if valid:
return checked_value
raise SpeckleException(
f"Cannot set '{self.__class__.__name__}.{name}': it expects type '{t.__name__}', but received type '{type(value).__name__}'"
f"Cannot set '{self.__class__.__name__}.{name}':"
f"it expects type '{str(t)}',"
f"but received type '{type(value).__name__}'"
)
def add_chunkable_attrs(self, **kwargs: int) -> None:
+3 -3
View File
@@ -1,5 +1,5 @@
from enum import Enum
from typing import Any, Callable, List, Type, Dict
from typing import Any, Callable, Dict, List, Optional, Type
from specklepy.logging.exceptions import SpeckleException
from specklepy.objects.base import Base
@@ -43,7 +43,7 @@ def curve_from_list(args: List[float]):
class ObjectArray:
def __init__(self, data: list = None) -> None:
def __init__(self, data: Optional[list] = None) -> None:
self.data = data or []
@classmethod
@@ -68,7 +68,7 @@ class ObjectArray:
def decode_data(
data: List[Any], decoder: Callable[[List[Any]], Base], **kwargs: Dict[str, Any]
) -> List[Base]:
bases = []
bases: List[Base] = []
if not data:
return bases
index = 0
+13 -12
View File
@@ -1,5 +1,6 @@
from enum import Enum
from typing import List
from typing import List, Optional
from specklepy.objects.geometry import Point
from .base import Base
@@ -16,8 +17,8 @@ DETACHABLE = {"detach_this", "origin", "detached_list"}
class FakeGeo(Base, chunkable={"dots": 50}, detachable={"pointslist"}):
pointslist: List[Base] = None
dots: List[int] = None
pointslist: Optional[List[Base]] = None
dots: Optional[List[int]] = None
class FakeDirection(Enum):
@@ -28,15 +29,15 @@ class FakeDirection(Enum):
class FakeMesh(FakeGeo, chunkable=CHUNKABLE_PROPS, detachable=DETACHABLE):
vertices: List[float] = None
faces: List[int] = None
colors: List[int] = None
textureCoordinates: List[float] = None
cardinal_dir: FakeDirection = None
test_bases: List[Base] = None
detach_this: Base = None
detached_list: List[Base] = None
_origin: Point = None
vertices: Optional[List[float]] = None
faces: Optional[List[int]] = None
colors: Optional[List[int]] = None
textureCoordinates: Optional[List[float]] = None
cardinal_dir: Optional[FakeDirection] = None
test_bases: Optional[List[Base]] = None
detach_this: Optional[Base] = None
detached_list: Optional[List[Base]] = None
_origin: Optional[Point] = None
# def __init__(self, **kwargs) -> None:
# super(FakeMesh, self).__init__(**kwargs)
+202 -155
View File
@@ -1,28 +1,14 @@
from enum import Enum
from enum import Enum, IntEnum, auto
from typing import Any, List, Optional
from .base import Base
from .encoding import CurveArray, CurveTypeEncoding, ObjectArray
from .units import get_encoding_from_units, get_units_from_encoding
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
GEOMETRY = "Objects.Geometry."
class Interval(Base, speckle_type="Objects.Primitive.Interval"):
start: float = 0.0
end: float = 0.0
def length(self):
return abs(self.start - self.end)
@classmethod
def from_list(cls, args: List[Any]) -> "Interval":
return cls(start=args[0], end=args[1])
def to_list(self) -> List[Any]:
return [self.start, self.end]
class Point(Base, speckle_type=GEOMETRY + "Point"):
x: float = 0.0
y: float = 0.0
@@ -47,12 +33,46 @@ class Point(Base, speckle_type=GEOMETRY + "Point"):
return pt
class Vector(Point, speckle_type=GEOMETRY + "Vector"):
pass
class Pointcloud(Base, speckle_type=GEOMETRY + "Pointcloud"):
points: Optional[List[float]] = None
colors: Optional[List[int]] = None
sizes: Optional[List[float]] = None
bbox: Optional["Box"] = None
class Vector(Base, speckle_type=GEOMETRY + "Vector"):
x: float = 0.0
y: float = 0.0
z: float = 0.0
applicationId: Optional[str] = None
def __repr__(self) -> str:
return (
f"{self.__class__.__name__} "
"(x: {self.x}, y: {self.y}, z: {self.z}, id: {self.id}, "
"speckle_type: {self.speckle_type})"
)
@classmethod
def from_list(cls, args: List[float]) -> "Vector":
"""
Create from a list of three floats representing the x, y, and z coordinates.
"""
return cls(x=args[0], y=args[1], z=args[2])
def to_list(self) -> List[float]:
return [self.x, self.y, self.z]
@classmethod
def from_coords(cls, x: float = 0.0, y: float = 0.0, z: float = 0.0) -> "Vector":
"""Create a new Point from x, y, and z values"""
v = Vector()
v.x, v.y, v.z = x, y, z
return v
class ControlPoint(Point, speckle_type=GEOMETRY + "ControlPoint"):
weight: float = None
weight: Optional[float] = None
class Plane(Base, speckle_type=GEOMETRY + "Plane"):
@@ -83,19 +103,19 @@ class Plane(Base, speckle_type=GEOMETRY + "Plane"):
class Box(Base, speckle_type=GEOMETRY + "Box"):
basePlane: Plane = Plane()
xSize: Interval = Interval()
ySize: Interval = Interval()
zSize: Interval = Interval()
xSize: Interval = Interval()
area: float = None
volume: float = None
area: Optional[float] = None
volume: Optional[float] = None
class Line(Base, speckle_type=GEOMETRY + "Line"):
start: Point = Point()
end: Point = None
domain: Interval = None
bbox: Box = None
length: float = None
end: Optional[Point] = None
domain: Optional[Interval] = None
bbox: Optional[Box] = None
length: Optional[float] = None
@classmethod
def from_list(cls, args: List[Any]) -> "Line":
@@ -118,18 +138,18 @@ class Line(Base, speckle_type=GEOMETRY + "Line"):
class Arc(Base, speckle_type=GEOMETRY + "Arc"):
radius: float = None
startAngle: float = None
endAngle: float = None
angleRadians: float = None
plane: Plane = None
domain: Interval = None
startPoint: Point = None
midPoint: Point = None
endPoint: Point = None
bbox: Box = None
area: float = None
length: float = None
radius: Optional[float] = None
startAngle: Optional[float] = None
endAngle: Optional[float] = None
angleRadians: Optional[float] = None
plane: Optional[Plane] = None
domain: Optional[Interval] = None
startPoint: Optional[Point] = None
midPoint: Optional[Point] = None
endPoint: Optional[Point] = None
bbox: Optional[Box] = None
area: Optional[float] = None
length: Optional[float] = None
@classmethod
def from_list(cls, args: List[Any]) -> "Arc":
@@ -163,12 +183,12 @@ class Arc(Base, speckle_type=GEOMETRY + "Arc"):
class Circle(Base, speckle_type=GEOMETRY + "Circle"):
radius: float = None
plane: Plane = None
domain: Interval = None
bbox: Box = None
area: float = None
length: float = None
radius: Optional[float] = None
plane: Optional[Plane] = None
domain: Optional[Interval] = None
bbox: Optional[Box] = None
area: Optional[float] = None
length: Optional[float] = None
@classmethod
def from_list(cls, args: List[Any]) -> "Circle":
@@ -190,14 +210,14 @@ class Circle(Base, speckle_type=GEOMETRY + "Circle"):
class Ellipse(Base, speckle_type=GEOMETRY + "Ellipse"):
firstRadius: float = None
secondRadius: float = None
plane: Plane = None
domain: Interval = None
trimDomain: Interval = None
bbox: Box = None
area: float = None
length: float = None
firstRadius: Optional[float] = None
secondRadius: Optional[float] = None
plane: Optional[Plane] = None
domain: Optional[Interval] = None
trimDomain: Optional[Interval] = None
bbox: Optional[Box] = None
area: Optional[float] = None
length: Optional[float] = None
@classmethod
def from_list(cls, args: List[Any]) -> "Ellipse":
@@ -221,12 +241,12 @@ class Ellipse(Base, speckle_type=GEOMETRY + "Ellipse"):
class Polyline(Base, speckle_type=GEOMETRY + "Polyline", chunkable={"value": 20000}):
value: List[float] = None
closed: bool = None
domain: Interval = None
bbox: Box = None
area: float = None
length: float = None
value: Optional[List[float]] = None
closed: Optional[bool] = None
domain: Optional[Interval] = None
bbox: Optional[Box] = None
area: Optional[float] = None
length: Optional[float] = None
@classmethod
def from_points(cls, points: List[Point]):
@@ -272,23 +292,50 @@ class Polyline(Base, speckle_type=GEOMETRY + "Polyline", chunkable={"value": 200
]
class SpiralType(Enum):
Biquadratic = (0,)
BiquadraticParabola = (1,)
Bloss = (2,)
Clothoid = (3,)
Cosine = (4,)
Cubic = (5,)
CubicParabola = (6,)
Radioid = (7,)
Sinusoid = (8,)
Unknown = 9
class Spiral(Base, speckle_type=GEOMETRY + "Spiral", detachable={"displayValue"}):
startPoint: Optional[Point] = None
endPoint: Optional[Point]
plane: Optional[Plane]
turns: Optional[int]
pitchAxis: Optional[Vector] = Vector()
pitch: float = 0
spiralType: Optional[SpiralType] = None
displayValue: Optional[Polyline] = None
bbox: Optional[Box] = None
length: Optional[float] = None
domain: Optional[Interval] = None
class Curve(
Base,
speckle_type=GEOMETRY + "Curve",
chunkable={"points": 20000, "weights": 20000, "knots": 20000},
):
degree: int = None
periodic: bool = None
rational: bool = None
points: List[float] = None
weights: List[float] = None
knots: List[float] = None
domain: Interval = None
displayValue: Polyline = None
closed: bool = None
bbox: Box = None
area: float = None
length: float = None
degree: Optional[int] = None
periodic: Optional[bool] = None
rational: Optional[bool] = None
points: Optional[List[float]] = None
weights: Optional[List[float]] = None
knots: Optional[List[float]] = None
domain: Optional[Interval] = None
displayValue: Optional[Polyline] = None
closed: Optional[bool] = None
bbox: Optional[Box] = None
area: Optional[float] = None
length: Optional[float] = None
def as_points(self) -> List[Point]:
"""Converts the `value` attribute to a list of Points"""
@@ -345,12 +392,12 @@ class Curve(
class Polycurve(Base, speckle_type=GEOMETRY + "Polycurve"):
segments: List[Base] = None
domain: Interval = None
closed: bool = None
bbox: Box = None
area: float = None
length: float = None
segments: Optional[List[Base]] = None
domain: Optional[Interval] = None
closed: Optional[bool] = None
bbox: Optional[Box] = None
area: Optional[float] = None
length: Optional[float] = None
@classmethod
def from_list(cls, args: List[Any]) -> "Polycurve":
@@ -375,17 +422,17 @@ class Polycurve(Base, speckle_type=GEOMETRY + "Polycurve"):
class Extrusion(Base, speckle_type=GEOMETRY + "Extrusion"):
capped: bool = None
profile: Base = None
pathStart: Point = None
pathEnd: Point = None
pathCurve: Base = None
pathTangent: Base = None
profiles: List[Base] = None
length: float = None
area: float = None
volume: float = None
bbox: Box = None
capped: Optional[bool] = None
profile: Optional[Base] = None
pathStart: Optional[Point] = None
pathEnd: Optional[Point] = None
pathCurve: Optional[Base] = None
pathTangent: Optional[Base] = None
profiles: Optional[List[Base]] = None
length: Optional[float] = None
area: Optional[float] = None
volume: Optional[float] = None
bbox: Optional[Box] = None
class Mesh(
@@ -398,21 +445,21 @@ class Mesh(
"textureCoordinates": 2000,
},
):
vertices: List[float] = None
faces: List[int] = None
colors: List[int] = None
textureCoordinates: List[float] = None
bbox: Box = None
area: float = None
volume: float = None
vertices: Optional[List[float]] = None
faces: Optional[List[int]] = None
colors: Optional[List[int]] = None
textureCoordinates: Optional[List[float]] = None
bbox: Optional[Box] = None
area: Optional[float] = None
volume: Optional[float] = None
@classmethod
def create(
cls,
vertices: List[float],
faces: List[int],
colors: List[int] = None,
texture_coordinates: List[float] = None,
colors: Optional[List[int]] = None,
texture_coordinates: Optional[List[float]] = None,
) -> "Mesh":
"""
Create a new Mesh from lists representing its vertices, faces,
@@ -430,20 +477,20 @@ class Mesh(
class Surface(Base, speckle_type=GEOMETRY + "Surface"):
degreeU: int = None
degreeV: int = None
rational: bool = None
area: float = None
pointData: List[float] = None
countU: int = None
countV: int = None
bbox: Box = None
closedU: bool = None
closedV: bool = None
domainU: Interval = None
domainV: Interval = None
knotsU: List[float] = None
knotsV: List[float] = None
degreeU: Optional[int] = None
degreeV: Optional[int] = None
rational: Optional[bool] = None
area: Optional[float] = None
pointData: Optional[List[float]] = None
countU: Optional[int] = None
countV: Optional[int] = None
bbox: Optional[Box] = None
closedU: Optional[bool] = None
closedV: Optional[bool] = None
domainU: Optional[Interval] = None
domainV: Optional[Interval] = None
knotsU: Optional[List[float]] = None
knotsV: Optional[List[float]] = None
@classmethod
def from_list(cls, args: List[Any]) -> "Surface":
@@ -493,11 +540,11 @@ class Surface(Base, speckle_type=GEOMETRY + "Surface"):
class BrepFace(Base, speckle_type=GEOMETRY + "BrepFace"):
_Brep: "Brep" = None
SurfaceIndex: int = None
OuterLoopIndex: int = None
OrientationReversed: bool = None
LoopIndices: List[int] = None
_Brep: Optional["Brep"] = None
SurfaceIndex: Optional[int] = None
OuterLoopIndex: Optional[int] = None
OrientationReversed: Optional[bool] = None
LoopIndices: Optional[List[int]] = None
@property
def _outer_loop(self):
@@ -533,13 +580,13 @@ class BrepFace(Base, speckle_type=GEOMETRY + "BrepFace"):
class BrepEdge(Base, speckle_type=GEOMETRY + "BrepEdge"):
_Brep: "Brep" = None
Curve3dIndex: int = None
TrimIndices: List[int] = None
StartIndex: int = None
EndIndex: int = None
ProxyCurveIsReversed: bool = None
Domain: Interval = None
_Brep: Optional["Brep"] = None
Curve3dIndex: Optional[int] = None
TrimIndices: Optional[List[int]] = None
StartIndex: Optional[int] = None
EndIndex: Optional[int] = None
ProxyCurveIsReversed: Optional[bool] = None
Domain: Optional[Interval] = None
@property
def _start_vertex(self):
@@ -600,10 +647,10 @@ class BrepLoopType(int, Enum):
class BrepLoop(Base, speckle_type=GEOMETRY + "BrepLoop"):
_Brep: "Brep" = None
FaceIndex: int = None
TrimIndices: List[int] = None
Type: BrepLoopType = None
_Brep: Optional["Brep"] = None
FaceIndex: Optional[Optional[int]] = None
TrimIndices: Optional[List[int]] = None
Type: Optional[BrepLoopType] = None
@property
def _face(self):
@@ -644,17 +691,17 @@ class BrepTrimType(int, Enum):
class BrepTrim(Base, speckle_type=GEOMETRY + "BrepTrim"):
_Brep: "Brep" = None
EdgeIndex: int = None
StartIndex: int = None
EndIndex: int = None
FaceIndex: int = None
LoopIndex: int = None
CurveIndex: int = None
IsoStatus: int = None
TrimType: BrepTrimType = None
IsReversed: bool = None
Domain: Interval = None
_Brep: Optional["Brep"] = None
EdgeIndex: Optional[int] = None
StartIndex: Optional[int] = None
EndIndex: Optional[int] = None
FaceIndex: Optional[int] = None
LoopIndex: Optional[int] = None
CurveIndex: Optional[int] = None
IsoStatus: Optional[int] = None
TrimType: Optional[BrepTrimType] = None
IsReversed: Optional[bool] = None
Domain: Optional[Interval] = None
@property
def _face(self):
@@ -731,21 +778,21 @@ class Brep(
"Faces",
},
):
provenance: str = None
bbox: Box = None
area: float = None
volume: float = None
_displayValue: List[Mesh] = None
Surfaces: List[Surface] = None
Curve3D: List[Base] = None
Curve2D: List[Base] = None
Vertices: List[Point] = None
Edges: List[BrepEdge] = None
Loops: List[BrepLoop] = None
Faces: List[BrepFace] = None
Trims: List[BrepTrim] = None
IsClosed: bool = None
Orientation: int = None
provenance: Optional[str] = None
bbox: Optional[Box] = None
area: Optional[float] = None
volume: Optional[float] = None
_displayValue: Optional[List[Mesh]] = None
Surfaces: Optional[List[Surface]] = None
Curve3D: Optional[List[Base]] = None
Curve2D: Optional[List[Base]] = None
Vertices: Optional[List[Point]] = None
Edges: Optional[List[BrepEdge]] = None
Loops: Optional[List[BrepLoop]] = None
Faces: Optional[List[BrepFace]] = None
Trims: Optional[List[BrepTrim]] = None
IsClosed: Optional[bool] = None
Orientation: Optional[int] = None
def _inject_self_into_children(self, children: Optional[List[Base]]) -> List[Base]:
if children is None:
+50 -14
View File
@@ -1,5 +1,7 @@
from typing import Any, List
from typing import Any, List, Optional
from specklepy.objects.geometry import Point, Vector
from .base import Base
OTHER = "Objects.Other."
@@ -24,8 +26,23 @@ IDENTITY_TRANSFORM = [
]
class Material(Base, speckle_type=OTHER + "Material"):
"""Generic class for materials containing generic parameters."""
name: Optional[str] = None
class RevitMaterial(Material, speckle_type="Objects.Other.Revit." + "RevitMaterial"):
materialCategory: Optional[str] = None
materialClass: Optional[str] = None
shininess: Optional[int] = None
smoothness: Optional[int] = None
transparency: Optional[int] = None
parameters: Optional[Base] = None
class RenderMaterial(Base, speckle_type=OTHER + "RenderMaterial"):
name: str = None
name: Optional[str] = None
opacity: float = 1
metalness: float = 0
roughness: float = 1
@@ -33,6 +50,25 @@ class RenderMaterial(Base, speckle_type=OTHER + "RenderMaterial"):
emissive: int = -16777216 # black arbg
class MaterialQuantity(Base, speckle_type=OTHER + "MaterialQuantity"):
material: Optional[Material] = None
volume: Optional[float] = None
area: Optional[float] = None
class DisplayStyle(Base, speckle_type=OTHER + "DisplayStyle"):
"""
Minimal display style class.
Developed primarily for display styles in Rhino and AutoCAD.
Rhino object attributes uses OpenNURBS definition for linetypes and lineweights.
"""
name: Optional[str] = None
color: int = -2894893 # light gray arbg
linetype: Optional[str] = None
lineweight: float = 0
class Transform(
Base,
speckle_type=OTHER + "Transform",
@@ -44,7 +80,7 @@ class Transform(
The 4th column defines translation, where the last value is a divisor (usually equal to 1).
"""
_value: List[float] = None
_value: Optional[List[float]] = None
@property
def value(self) -> List[float]:
@@ -188,27 +224,27 @@ class Transform(
class BlockDefinition(
Base, speckle_type=OTHER + "BlockDefinition", detachable={"geometry"}
):
name: str = None
basePoint: Point = None
geometry: List[Base] = None
name: Optional[str] = None
basePoint: Optional[Point] = None
geometry: Optional[List[Base]] = None
class BlockInstance(
Base, speckle_type=OTHER + "BlockInstance", detachable={"blockDefinition"}
):
blockDefinition: BlockDefinition = None
transform: Transform = None
blockDefinition: Optional[BlockDefinition] = None
transform: Optional[Transform] = None
# TODO: prob move this into a built elements module, but just trialling this for now
class RevitParameter(Base, speckle_type="Objects.BuiltElements.Revit.Parameter"):
name: str = None
name: Optional[str] = None
value: Any = None
applicationUnitType: str = None # eg UnitType UT_Length
applicationUnit: str = None # DisplayUnitType eg DUT_MILLIMITERS
applicationInternalName: str = (
None # BuiltInParameterName or GUID for shared parameter
)
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
isShared: bool = False
isReadOnly: bool = False
isTypeParameter: bool = False
+25
View File
@@ -0,0 +1,25 @@
from typing import Any, List
from specklepy.objects.base import Base
NAMESPACE = "Objects.Primitive"
class Interval(Base, speckle_type=f"{NAMESPACE}.Interval"):
start: float = 0.0
end: float = 0.0
def length(self):
return abs(self.start - self.end)
@classmethod
def from_list(cls, args: List[Any]) -> "Interval":
return cls(start=args[0], end=args[1])
def to_list(self) -> List[Any]:
return [self.start, self.end]
class Interval2d(Base, speckle_type=f"{NAMESPACE}.Interval2d"):
u: Interval
v: Interval
+107 -6
View File
@@ -1,20 +1,99 @@
"""Builtin Speckle object kit."""
from specklepy.objects.structural.analysis import *
from specklepy.objects.structural.properties import *
from specklepy.objects.structural.material import *
from specklepy.objects.structural.geometry import *
from specklepy.objects.structural.loading import *
from specklepy.objects.structural.analysis import (
Model,
ModelInfo,
ModelSettings,
ModelUnits,
)
from specklepy.objects.structural.axis import Axis
from specklepy.objects.structural.geometry import (
Element1D,
Element2D,
Element3D,
ElementType1D,
ElementType2D,
ElementType3D,
Node,
Restraint,
)
from specklepy.objects.structural.loading import (
ActionType,
BeamLoadType,
CombinationType,
FaceLoadType,
Load,
LoadAxisType,
LoadBeam,
LoadCase,
LoadCombinations,
LoadDirection,
LoadDirection2D,
LoadFace,
LoadGravity,
LoadNode,
LoadType,
)
from specklepy.objects.structural.material import (
Concrete,
MaterialType,
Steel,
StructuralMaterial,
Timber,
)
from specklepy.objects.structural.properties import (
BaseReferencePoint,
MemberType,
Property,
Property1D,
Property2D,
Property3D,
PropertyDamper,
PropertyMass,
PropertySpring,
PropertyType2D,
PropertyType3D,
PropertyTypeDamper,
PropertyTypeSpring,
ReferenceSurface,
ReferenceSurfaceEnum,
SectionProfile,
ShapeType,
shapeType,
)
from specklepy.objects.structural.results import (
Result,
Result1D,
Result2D,
Result3D,
ResultGlobal,
ResultNode,
ResultSet1D,
ResultSet2D,
ResultSet3D,
ResultSetAll,
ResultSetNode,
)
__all__ = [
"Element1D",
"Element2D",
"Element3D",
"ElementType1D",
"ElementType2D",
"ElementType3D",
"Axis",
"Node",
"Restraint",
"Load",
"LoadType",
"ActionType",
"BeamLoadType",
"FaceLoadType",
"LoadDirection",
"LoadDirection2D",
"LoadAxisType",
"CombinationType",
"LoadBeam",
"LoadCase",
"LoadCombinations",
@@ -25,8 +104,9 @@ __all__ = [
"ModelInfo",
"ModelSettings",
"ModelUnits",
"MaterialType",
"Concrete",
"Material",
"StructuralMaterial",
"Steel",
"Timber",
"Property",
@@ -37,4 +117,25 @@ __all__ = [
"PropertyMass",
"PropertySpring",
"SectionProfile",
"MemberType",
"BaseReferencePoint",
"ReferenceSurface",
"PropertyType2D",
"PropertyType3D",
"ShapeType",
"PropertyTypeSpring",
"PropertyTypeDamper",
"ReferenceSurfaceEnum",
"shapeType",
"Result",
"Result1D",
"ResultSet1D",
"Result2D",
"ResultSet2D",
"Result3D",
"ResultSet3D",
"ResultGlobal",
"ResultSetNode",
"ResultNode",
"ResultSetAll",
]
+33 -35
View File
@@ -1,51 +1,49 @@
from typing import List
from typing import List, Optional
from ..base import Base
from ..geometry import *
from .properties import *
from specklepy.objects.base import Base
STRUCTURAL_ANALYSIS = "Objects.Structural.Analysis."
class ModelUnits(Base, speckle_type=STRUCTURAL_ANALYSIS + "ModelUnits"):
length: str = None
sections: str = None
displacements: str = None
stress: str = None
force: str = None
mass: str = None
time: str = None
temperature: str = None
velocity: str = None
acceleration: str = None
energy: str = None
angle: str = None
strain: str = None
length: Optional[str] = None
sections: Optional[str] = None
displacements: Optional[str] = None
stress: Optional[str] = None
force: Optional[str] = None
mass: Optional[str] = None
time: Optional[str] = None
temperature: Optional[str] = None
velocity: Optional[str] = None
acceleration: Optional[str] = None
energy: Optional[str] = None
angle: Optional[str] = None
strain: Optional[str] = None
class ModelSettings(Base, speckle_type=STRUCTURAL_ANALYSIS + "ModelSettings"):
modelUnits: ModelUnits = None
steelCode: str = None
concreteCode: str = None
modelUnits: Optional[ModelUnits] = None
steelCode: Optional[str] = None
concreteCode: Optional[str] = None
coincidenceTolerance: float = 0.0
class ModelInfo(Base, speckle_type=STRUCTURAL_ANALYSIS + "ModelInfo"):
name: str = None
description: str = None
projectNumber: str = None
projectName: str = None
settings: ModelSettings = None
initials: str = None
application: str = None
name: Optional[str] = None
description: Optional[str] = None
projectNumber: Optional[str] = None
projectName: Optional[str] = None
settings: Optional[ModelSettings] = None
initials: Optional[str] = None
application: Optional[str] = None
class Model(Base, speckle_type=STRUCTURAL_ANALYSIS + "Model"):
specs: ModelInfo = None
nodes: List = None
elements: List = None
loads: List = None
restraints: List = None
properties: List = None
materials: List = None
layerDescription: str = None
specs: Optional[ModelInfo] = None
nodes: Optional[List] = None
elements: Optional[List] = None
loads: Optional[List] = None
restraints: Optional[List] = None
properties: Optional[List] = None
materials: Optional[List] = None
layerDescription: Optional[str] = None
+7 -5
View File
@@ -1,8 +1,10 @@
from ..base import Base
from ..geometry import Plane
from typing import Optional
from specklepy.objects.base import Base
from specklepy.objects.geometry import Plane
class Axis(Base, speckle_type="Objects.Structural.Geometry.Axis"):
name: str = None
axisType: str = None
plane: Plane = None
name: Optional[str] = None
axisType: Optional[str] = None
plane: Optional[Plane] = None
+46 -44
View File
@@ -1,10 +1,17 @@
from enum import Enum
from typing import List
from typing import List, Optional
from ..base import Base
from ..geometry import *
from .properties import *
from .axis import Axis
from specklepy.objects.base import Base
from specklepy.objects.geometry import Line, Mesh, Plane, Point, Vector
from specklepy.objects.structural.axis import Axis
from specklepy.objects.structural.properties import (
Property1D,
Property2D,
Property3D,
PropertyDamper,
PropertyMass,
PropertySpring,
)
STRUCTURAL_GEOMETRY = "Objects.Structural.Geometry"
@@ -41,68 +48,63 @@ class ElementType3D(int, Enum):
class Restraint(Base, speckle_type=STRUCTURAL_GEOMETRY + ".Restraint"):
code: str = None
code: Optional[str] = None
stiffnessX: float = 0.0
stiffnessY: float = 0.0
stiffnessZ: float = 0.0
stiffnessXX: float = 0.0
stiffnessYY: float = 0.0
stiffnessZZ: float = 0.0
units: str = None
class Node(Base, speckle_type=STRUCTURAL_GEOMETRY + ".Node"):
name: str = None
basePoint: Point = None
constraintAxis: Axis = None
restraint: Restraint = None
springProperty: PropertySpring = None
massProperty: PropertyMass = None
damperProperty: PropertyDamper = None
units: str = None
name: Optional[str] = None
basePoint: Optional[Point] = None
constraintAxis: Optional[Axis] = None
restraint: Optional[Restraint] = None
springProperty: Optional[PropertySpring] = None
massProperty: Optional[PropertyMass] = None
damperProperty: Optional[PropertyDamper] = None
class Element1D(Base, speckle_type=STRUCTURAL_GEOMETRY + ".Element1D"):
name: str = None
baseLine: Line = None
property: Property1D = None
type: ElementType1D = None
end1Releases: Restraint = None
end2Releases: Restraint = None
end1Offset: Vector = None
end2Offset: Vector = None
orientationNode: Node = None
name: Optional[str] = None
baseLine: Optional[Line] = None
property: Optional[Property1D] = None
type: Optional[ElementType1D] = None
end1Releases: Optional[Restraint] = None
end2Releases: Optional[Restraint] = None
end1Offset: Optional[Vector] = None
end2Offset: Optional[Vector] = None
orientationNode: Optional[Node] = None
orinetationAngle: float = 0.0
localAxis: Plane = None
parent: Base = None
end1Node: Node = Node
end2Node: Node = Node
topology: List = None
displayMesh: Mesh = None
units: str = None
localAxis: Optional[Plane] = None
parent: Optional[Base] = None
end1Node: Optional[Node] = None
end2Node: Optional[Node] = None
topology: Optional[List] = None
displayMesh: Optional[Mesh] = None
class Element2D(Base, speckle_type=STRUCTURAL_GEOMETRY + ".Element2D"):
name: str = None
property: Property2D = None
type: ElementType2D = None
name: Optional[str] = None
property: Optional[Property2D] = None
type: Optional[ElementType2D] = None
offset: float = 0.0
orientationAngle: float = 0.0
parent: Base = None
topology: List = None
displayMesh: Mesh = None
units: str = None
parent: Optional[Base] = None
topology: Optional[List] = None
displayMesh: Optional[Mesh] = None
class Element3D(Base, speckle_type=STRUCTURAL_GEOMETRY + ".Element3D"):
name: str = None
baseMesh: Mesh = None
property: Property3D = None
type: ElementType3D = None
name: Optional[str] = None
baseMesh: Optional[Mesh] = None
property: Optional[Property3D] = None
type: Optional[ElementType3D] = None
orientationAngle: float = 0.0
parent: Base = None
parent: Optional[Base] = None
topology: List
units: str = None
# class Storey needs ependency on built elements first
+34 -34
View File
@@ -1,8 +1,9 @@
from enum import Enum
from typing import List
from typing import List, Optional
from ..base import Base
from .geometry import *
from specklepy.objects.base import Base
from specklepy.objects.geometry import Vector
from specklepy.objects.structural.axis import Axis
STRUCTURAL_LOADING = "Objects.Structural.Loading."
@@ -89,56 +90,55 @@ class CombinationType(int, Enum):
class LoadCase(Base, speckle_type=STRUCTURAL_LOADING + "LoadCase"):
name: str = None
loadType: LoadType = None
group: str = None
actionType: ActionType = None
description: str = None
name: Optional[str] = None
loadType: Optional[LoadType] = None
group: Optional[str] = None
actionType: Optional[ActionType] = None
description: Optional[str] = None
class Load(Base, speckle_type=STRUCTURAL_LOADING + "Load"):
name: str = None
units: str = None
loadCase: LoadCase = None
name: Optional[str] = None
loadCase: Optional[LoadCase] = None
class LoadBeam(Load, speckle_type=STRUCTURAL_LOADING + "LoadBeam"):
elements: List = None
loadType: BeamLoadType = None
direction: LoadDirection = None
loadAxis: Axis = None
loadAxisType: LoadAxisType = None
isProjected: bool = None
values: List = None
positions: List = None
elements: Optional[List] = None
loadType: Optional[BeamLoadType] = None
direction: Optional[LoadDirection] = None
loadAxis: Optional[Axis] = None
loadAxisType: Optional[LoadAxisType] = None
isProjected: Optional[bool] = None
values: Optional[List] = None
positions: Optional[List] = None
class LoadCombinations(Base, speckle_type=STRUCTURAL_LOADING + "LoadCombination"):
name: str = None
name: Optional[str] = None
loadCases: List
loadFactors: List
combinationType: CombinationType
class LoadFace(Load, speckle_type=STRUCTURAL_LOADING + "LoadFace"):
elements: List = None
loadType: FaceLoadType = None
direction: LoadDirection2D = None
loadAxis: Axis = None
loadAxisType: LoadAxisType = None
isProjected: bool = None
values: List = None
positions: List = None
elements: Optional[List] = None
loadType: Optional[FaceLoadType] = None
direction: Optional[LoadDirection2D] = None
loadAxis: Optional[Axis] = None
loadAxisType: Optional[LoadAxisType] = None
isProjected: Optional[bool] = None
values: Optional[List] = None
positions: Optional[List] = None
class LoadGravity(Load, speckle_type=STRUCTURAL_LOADING + "LoadGravity"):
elements: List = None
nodes: List = None
gravityFactors: Vector = None
elements: Optional[List] = None
nodes: Optional[List] = None
gravityFactors: Optional[Vector] = None
class LoadNode(Load, speckle_type=STRUCTURAL_LOADING + "LoadNode"):
nodes: List = None
loadAxis: Axis = None
direction: LoadDirection = None
nodes: Optional[List] = None
loadAxis: Optional[Axis] = None
direction: Optional[LoadDirection] = None
value: float = 0.0
+15 -13
View File
@@ -1,7 +1,7 @@
from enum import Enum
from typing import Optional
from ..base import Base
from specklepy.objects.base import Base
STRUCTURAL_MATERIALS = "Objects.Structural.Materials"
@@ -21,12 +21,14 @@ class MaterialType(int, Enum):
Other = 11
class Material(Base, speckle_type=STRUCTURAL_MATERIALS):
name: str = None
grade: str = None
materialType: MaterialType = None
designCode: str = None
codeYear: str = None
class StructuralMaterial(
Base, speckle_type=STRUCTURAL_MATERIALS + ".StructuralMaterial"
):
name: Optional[str] = None
grade: Optional[str] = None
materialType: Optional[MaterialType] = None
designCode: Optional[str] = None
codeYear: Optional[str] = None
strength: float = 0.0
elasticModulus: float = 0.0
poissonsRatio: float = 0.0
@@ -38,22 +40,22 @@ class Material(Base, speckle_type=STRUCTURAL_MATERIALS):
materialSafetyFactor: float = 0.0
class Concrete(Material, speckle_type=STRUCTURAL_MATERIALS + ".Concrete"):
class Concrete(StructuralMaterial, speckle_type=STRUCTURAL_MATERIALS + ".Concrete"):
compressiveStrength: float = 0.0
tensileStrength: float = 0.0
flexuralStrength: float = 0.0
maxCompressiveStrain: float = 0.0
maxTensileStrain: float = 0.0
maxAggregateSize: float = 0.0
lightweight: bool = None
lightweight: Optional[bool] = None
class Steel(Material, speckle_type=STRUCTURAL_MATERIALS + ".Steel"):
class Steel(StructuralMaterial, speckle_type=STRUCTURAL_MATERIALS + ".Steel"):
yieldStrength: float = 0.0
ultimateStrength: float = 0.0
maxStrain: float = 0.0
strainHardeningModulus: float = 0.0
class Timber(Material, speckle_type=STRUCTURAL_MATERIALS + ".Timber"):
species: str = None
class Timber(StructuralMaterial, speckle_type=STRUCTURAL_MATERIALS + ".Timber"):
species: Optional[str] = None
+22 -24
View File
@@ -1,10 +1,9 @@
from enum import Enum
from typing import Optional
from ..base import Base
from .material import *
from .axis import Axis
from specklepy.objects.base import Base
from specklepy.objects.structural.axis import Axis
from specklepy.objects.structural.material import StructuralMaterial
STRUCTURAL_PROPERTY = "Objectives.Structural.Properties"
@@ -59,7 +58,7 @@ class PropertyType3D(int, Enum):
class ShapeType(int, Enum):
Rectangular = 0
Circular = 1
I = 2
I = 2 # noqa: E741
Tee = 3
Angle = 4
Channel = 5
@@ -89,36 +88,35 @@ class PropertyTypeDamper(int, Enum):
class Property(Base, speckle_type=STRUCTURAL_PROPERTY):
name: str = None
name: Optional[str] = None
class SectionProfile(Base, speckle_type=STRUCTURAL_PROPERTY + ".SectionProfile"):
name: str = None
shapeType: ShapeType = None
name: Optional[str] = None
shapeType: Optional[ShapeType] = None
area: float = 0.0
Iyy: float = 0.0
Izz: float = 0.0
J: float = 0.0
Ky: float = 0.0
weight: float = 0.0
units: str = None
class Property1D(Property, speckle_type=STRUCTURAL_PROPERTY + ".Property1D"):
memberType: MemberType = None
material : Material = None
profile: SectionProfile = None
referencePoint : BaseReferencePoint = None
memberType: Optional[MemberType] = None
material: Optional[StructuralMaterial] = None
profile: Optional[SectionProfile] = None
referencePoint: Optional[BaseReferencePoint] = None
offsetY: float = 0.0
offsetZ: float = 0.0
class Property2D(Property, speckle_type=STRUCTURAL_PROPERTY + ".Property2D"):
type: PropertyType2D = None
type: Optional[PropertyType2D] = None
thickness: float = 0.0
material: Material = None
orientationAxis : Axis = None
refSurface : ReferenceSurface = None
material: Optional[StructuralMaterial] = None
orientationAxis: Optional[Axis] = None
refSurface: Optional[ReferenceSurface] = None
zOffset: float = 0.0
modifierInPlane: float = 0.0
modifierBending: float = 0.0
@@ -127,13 +125,13 @@ class Property2D(Property, speckle_type=STRUCTURAL_PROPERTY + ".Property2D"):
class Property3D(Property, speckle_type=STRUCTURAL_PROPERTY + ".Property3D"):
type: PropertyType3D = None
material: Material = None
orientationAxis: Axis = None
type: Optional[PropertyType3D] = None
material: Optional[StructuralMaterial] = None
orientationAxis: Optional[Axis] = None
class PropertyDamper(Property, speckle_type=STRUCTURAL_PROPERTY + ".PropertyDamper"):
damperType: PropertyTypeDamper = None
damperType: Optional[PropertyTypeDamper] = None
dampingX: float = 0.0
dampingY: float = 0.0
dampingZ: float = 0.0
@@ -150,14 +148,14 @@ class PropertyMass(Property, speckle_type=STRUCTURAL_PROPERTY + ".PropertyMass")
inertiaXY: float = 0.0
inertiaYZ: float = 0.0
inertiaZX: float = 0.0
massModified: bool = None
massModified: Optional[bool] = None
massModifierX: float = 0.0
massModifierY: float = 0.0
massModifierZ: float = 0.0
class PropertySpring(Property, speckle_type=STRUCTURAL_PROPERTY + ".PropertySpring"):
springType: PropertyTypeSpring = None
springType: Optional[PropertyTypeSpring] = None
springCurveX: float = 0.0
stiffnessX: float = 0.0
springCurveY: float = 0.0
+17 -19
View File
@@ -1,18 +1,16 @@
from typing import List
from typing import List, Optional
from ..base import Base
from ..geometry import *
from .loading import *
from .geometry import *
from .analysis import Model
from specklepy.objects.base import Base
from specklepy.objects.structural.analysis import Model
from specklepy.objects.structural.geometry import Element1D, Element2D, Element3D, Node
STRUCTURAL_RESULTS = "Objects.Structural.Results."
class Result(Base, speckle_type=STRUCTURAL_RESULTS + "Result"):
resultCase: Base = None
permutation: str = None
description: str = None
resultCase: Optional[Base] = None
permutation: Optional[str] = None
description: Optional[str] = None
class ResultSet1D(Result, speckle_type=STRUCTURAL_RESULTS + "ResultSet1D"):
@@ -20,7 +18,7 @@ class ResultSet1D(Result, speckle_type=STRUCTURAL_RESULTS + "ResultSet1D"):
class Result1D(Result, speckle_type=STRUCTURAL_RESULTS + "Result1D"):
element: Element1D = None
element: Optional[Element1D] = None
position: float = 0.0
dispX: float = 0.0
dispY: float = 0.0
@@ -50,7 +48,7 @@ class ResultSet2D(Result, speckle_type=STRUCTURAL_RESULTS + "ResultSet2D"):
class Result2D(Result, speckle_type=STRUCTURAL_RESULTS + "Result2D"):
element: Element2D = None
element: Optional[Element2D] = None
position: List
dispX: float = 0.0
dispY: float = 0.0
@@ -88,7 +86,7 @@ class ResultSet3D(Result, speckle_type=STRUCTURAL_RESULTS + "ResultSet3D"):
class Result3D(Result, speckle_type=STRUCTURAL_RESULTS + "Result3D"):
element: Element3D = None
element: Optional[Element3D] = None
position: List
dispX: float = 0.0
dispY: float = 0.0
@@ -102,7 +100,7 @@ class Result3D(Result, speckle_type=STRUCTURAL_RESULTS + "Result3D"):
class ResultGlobal(Result, speckle_type=STRUCTURAL_RESULTS + "ResultGlobal"):
model: Model = None
model: Optional[Model] = None
loadX: float = 0.0
loadY: float = 0.0
loadZ: float = 0.0
@@ -133,7 +131,7 @@ class ResultSetNode(Result, speckle_type=STRUCTURAL_RESULTS + "ResultSetNode"):
class ResultNode(Result, speckle_type=STRUCTURAL_RESULTS + " ResultNode"):
node: Node = None
node: Optional[Node] = None
dispX: float = 0.0
dispY: float = 0.0
dispZ: float = 0.0
@@ -167,8 +165,8 @@ class ResultNode(Result, speckle_type=STRUCTURAL_RESULTS + " ResultNode"):
class ResultSetAll(Base, speckle_type=None):
resultSet1D: ResultSet1D = None
resultSet2D: ResultSet2D = None
resultSet3D: ResultSet3D = None
resultsGlobal: ResultGlobal = None
resultsNode: ResultSetNode = None
resultSet1D: Optional[ResultSet1D] = None
resultSet2D: Optional[ResultSet2D] = None
resultSet3D: Optional[ResultSet3D] = None
resultsGlobal: Optional[ResultGlobal] = None
resultsNode: Optional[ResultSetNode] = None
+18 -4
View File
@@ -1,6 +1,14 @@
from typing import Union
from specklepy.logging.exceptions import SpeckleException, SpeckleInvalidUnitException
from enum import Enum
from typing import Union
from specklepy.logging.exceptions import SpeckleException, SpeckleInvalidUnitException
__all__ = [
"Units",
"get_encoding_from_units",
"get_units_from_encoding",
"get_units_from_string",
]
class Units(Enum):
@@ -57,7 +65,10 @@ def get_units_from_encoding(unit: int):
return name
raise SpeckleException(
message=f"Could not understand what unit {unit} is referring to. Please enter a valid unit encoding (eg {UNITS_ENCODINGS})."
message=(
f"Could not understand what unit {unit} is referring to."
f"Please enter a valid unit encoding (eg {UNITS_ENCODINGS})."
)
)
@@ -66,5 +77,8 @@ def get_encoding_from_units(unit: Union[Units, None]):
return UNITS_ENCODINGS[unit]
except KeyError as e:
raise SpeckleException(
message=f"No encoding exists for unit {unit}. Please enter a valid unit to encode (eg {UNITS_ENCODINGS})."
message=(
f"No encoding exists for unit {unit}."
f"Please enter a valid unit to encode (eg {UNITS_ENCODINGS})."
)
) from e
+1
View File
@@ -1,5 +1,6 @@
import sys
from pathlib import Path
from appdirs import user_data_dir
@@ -1,21 +1,19 @@
import re
import ujson
import hashlib
import re
import warnings
from uuid import uuid4
from enum import Enum
from warnings import warn
from typing import Any, Dict, List, Tuple
from specklepy.objects.base import Base, DataChunk
from specklepy.logging.exceptions import (
SpeckleException,
SpeckleWarning,
)
from specklepy.transports.abstract_transport import AbstractTransport
from uuid import uuid4
from warnings import warn
import ujson
# import for serialization
import specklepy.objects.geometry
import specklepy.objects.other
from specklepy.logging.exceptions import SpeckleException, SpeckleWarning
from specklepy.objects.base import Base, DataChunk
from specklepy.transports.abstract_transport import AbstractTransport
PRIMITIVES = (int, float, str, bool)
@@ -1,5 +1,6 @@
from abc import ABC, abstractmethod
from typing import Optional, List, Dict
from typing import Dict, List, Optional
from pydantic import BaseModel
from pydantic.config import Extra
+2 -1
View File
@@ -1,4 +1,5 @@
from typing import Any, List, Dict
from typing import Any, Dict, List
from specklepy.transports.abstract_transport import AbstractTransport
@@ -1,10 +1,11 @@
import gzip
import json
import logging
import threading
import queue
import gzip
import threading
import requests
from specklepy.logging.exceptions import SpeckleException
LOG = logging.getLogger(__name__)
+2 -2
View File
@@ -1,8 +1,8 @@
import json
import requests
from typing import Any, Dict, List
from warnings import warn
from typing import Any, Dict, List
import requests
from specklepy.api.client import SpeckleClient
from specklepy.api.credentials import Account, get_account_from_token
+3 -2
View File
@@ -1,10 +1,11 @@
import os
import sqlite3
from typing import Any, List, Dict, Optional, Tuple
from contextlib import closing
from specklepy.transports.abstract_transport import AbstractTransport
from typing import Any, Dict, List, Optional, Tuple
from specklepy.logging.exceptions import SpeckleException
from specklepy.paths import base_path
from specklepy.transports.abstract_transport import AbstractTransport
class SQLiteTransport(AbstractTransport):
+9 -7
View File
@@ -1,13 +1,15 @@
import uuid
import random
import uuid
import pytest
import requests
from specklepy.api.models import Stream
from specklepy.api.client import SpeckleClient
from specklepy.objects.base import Base
from specklepy.objects.geometry import Point
from specklepy.objects.fakemesh import FakeDirection, FakeMesh
from specklepy.api.models import Stream
from specklepy.logging import metrics
from specklepy.objects.base import Base
from specklepy.objects.fakemesh import FakeDirection, FakeMesh
from specklepy.objects.geometry import Point
metrics.disable()
@@ -29,10 +31,10 @@ def seed_user(host):
r = requests.post(
url=f"http://{host}/auth/local/register?challenge=pyspeckletests",
data=user_dict,
# do not follow redirects here, they lead to the frontend, which might not be
# do not follow redirects here, they lead to the frontend, which might not be
# running in a test environment
# causing the response to not be OK in the end
allow_redirects=False
allow_redirects=False,
)
if not r.ok:
raise Exception(f"Cannot seed user: {r.reason}")
+1
View File
@@ -1,4 +1,5 @@
import pytest
from specklepy.api.client import SpeckleClient
from specklepy.api.models import Activity, ActivityCollection, User
from specklepy.logging.exceptions import SpeckleException
+9 -5
View File
@@ -1,12 +1,12 @@
from codecs import ascii_encode
from contextlib import ExitStack as does_not_raise
from enum import Enum
from typing import Dict, List, Optional, Union
from contextlib import ExitStack as does_not_raise
import pytest
from specklepy.api import operations
from specklepy.logging.exceptions import SpeckleException, SpeckleInvalidUnitException
from specklepy.objects.base import Base, DataChunk
from specklepy.objects.base import Base
from specklepy.objects.units import Units
@@ -29,12 +29,15 @@ def test_empty_prop_names(invalid_prop_name: str) -> None:
class FakeModel(Base):
"""Just a test class type."""
foo: str = ""
class FakeSub(FakeModel):
"""Just a test class type."""
def test_new_type_registration() -> None:
"""Test if a new subclass is registered into the type register."""
assert Base.get_registered_type("FakeModel") == FakeModel
assert Base.get_registered_type(FakeModel.speckle_type) == FakeModel
assert Base.get_registered_type(FakeSub.speckle_type) == FakeSub
assert Base.get_registered_type("🐺️") is None
@@ -150,6 +153,7 @@ def test_type_checking() -> None:
order.flavours = ["strawberry", "lychee", "peach", "pineapple"]
assert order.price == 7.0
assert order.dietary == DietaryRestrictions.VEGAN
def test_cached_deserialization() -> None:
+2 -1
View File
@@ -1,7 +1,8 @@
import pytest
from specklepy.api import operations
from specklepy.transports.server import ServerTransport
from specklepy.api.models import Branch, Commit, Stream
from specklepy.transports.server import ServerTransport
class TestBranch:
+3 -2
View File
@@ -1,10 +1,11 @@
import pytest
from specklepy.api import operations
from specklepy.api.client import SpeckleClient
from specklepy.objects.base import Base
from specklepy.transports.server import ServerTransport
from specklepy.api.credentials import Account, get_account_from_token
from specklepy.logging.exceptions import SpeckleException, SpeckleWarning
from specklepy.objects.base import Base
from specklepy.transports.server import ServerTransport
def test_invalid_authentication():
+1
View File
@@ -1,4 +1,5 @@
import pytest
from specklepy.api import operations
from specklepy.api.models import Commit, Stream
from specklepy.transports.server.server import ServerTransport
+2 -1
View File
@@ -2,10 +2,10 @@
import json
import pytest
from specklepy.api import operations
from specklepy.logging.exceptions import SpeckleException
from specklepy.objects.base import Base
from specklepy.objects.units import Units
from specklepy.objects.encoding import CurveArray, ObjectArray
from specklepy.objects.geometry import (
Arc,
@@ -30,6 +30,7 @@ from specklepy.objects.geometry import (
Surface,
Vector,
)
from specklepy.objects.units import Units
from specklepy.transports.memory import MemoryTransport
+2 -1
View File
@@ -1,7 +1,8 @@
import pytest
from specklepy.api.host_applications import (
get_host_app_from_string,
_app_name_host_app_mapping,
get_host_app_from_string,
)
+1
View File
@@ -1,4 +1,5 @@
import pytest
from specklepy.api.models import Stream
from specklepy.objects import Base
from specklepy.objects.encoding import ObjectArray
+1
View File
@@ -1,4 +1,5 @@
import pytest
from specklepy.api.client import SpeckleClient
from specklepy.api.models import Activity, ActivityCollection, LimitedUser
from specklepy.logging.exceptions import SpeckleException
+35
View File
@@ -0,0 +1,35 @@
from typing import Type
import pytest
from specklepy.objects.base import Base
from specklepy.objects.structural import Concrete
class Foo(Base):
"""This is a Foo inheriting from Base."""
class Bar(Foo, speckle_type="Custom.Bar"):
"""This is a Bar inheriting from Foo."""
class Baz(Bar):
"""This is a Bar inheriting from Foo."""
@pytest.mark.parametrize(
"klass, speckle_type",
[
(Base, "Base"),
(Foo, "Foo"),
(Bar, "Foo:Custom.Bar"),
(Baz, "Foo:Custom.Bar:Baz"),
(
Concrete,
"Objects.Structural.Materials.StructuralMaterial:Objects.Structural.Materials.Concrete",
),
],
)
def test_determine_speckle_type(klass: Type[Base], speckle_type: str):
assert klass._determine_speckle_type() == speckle_type
+6 -4
View File
@@ -1,12 +1,14 @@
import json
import pytest
from specklepy.api import operations
from specklepy.transports.server import ServerTransport
from specklepy.transports.memory import MemoryTransport
from specklepy.serialization.base_object_serializer import BaseObjectSerializer
from specklepy.objects import Base
from specklepy.objects.geometry import Point
from specklepy.objects.fakemesh import FakeMesh
from specklepy.objects.geometry import Point
from specklepy.serialization.base_object_serializer import BaseObjectSerializer
from specklepy.transports.memory import MemoryTransport
from specklepy.transports.server import ServerTransport
@pytest.mark.run(order=5)
+2 -1
View File
@@ -1,6 +1,7 @@
import pytest
from specklepy.api.models import ServerInfo
from specklepy.api.client import SpeckleClient
from specklepy.api.models import ServerInfo
class TestServer:
+5 -3
View File
@@ -1,13 +1,15 @@
import pytest
from datetime import datetime
import pytest
from specklepy.api.client import SpeckleClient
from specklepy.api.models import (
ActivityCollection,
Activity,
ActivityCollection,
PendingStreamCollaborator,
Stream,
User,
)
from specklepy.api.client import SpeckleClient
from specklepy.logging.exceptions import (
GraphQLException,
SpeckleException,
+9 -24
View File
@@ -1,39 +1,24 @@
import json
from typing import Callable
import pytest
from specklepy.api import operations
from specklepy.logging.exceptions import SpeckleException
from specklepy.objects.base import Base
from specklepy.objects.encoding import CurveArray, ObjectArray
from specklepy.objects.geometry import (
Line,
Mesh,
Point,
Vector,
)
from specklepy.transports.memory import MemoryTransport
from specklepy.objects.geometry import Line, Mesh, Point, Vector
from specklepy.objects.structural.analysis import Model
from specklepy.objects.structural.geometry import (
Node,
Element1D,
Element2D,
Restraint,
ElementType1D,
ElementType2D,
Node,
Restraint,
)
from specklepy.objects.structural.loading import LoadGravity
from specklepy.objects.structural.material import StructuralMaterial
from specklepy.objects.structural.properties import (
MemberType,
Property1D,
Property2D,
SectionProfile,
MemberType,
ShapeType,
)
from specklepy.objects.structural.material import (
Material,
)
from specklepy.objects.structural.analysis import Model
from specklepy.objects.structural.loading import LoadGravity
@pytest.fixture()
@@ -82,7 +67,7 @@ def node(restraint, point):
@pytest.fixture()
def material():
return Material(name="TestMaterial")
return StructuralMaterial(name="TestMaterial")
@pytest.fixture()
+5 -3
View File
@@ -1,12 +1,14 @@
from typing import List
import pytest
from specklepy.api import operations
from specklepy.objects.geometry import Point, Vector
from specklepy.objects.other import (
Transform,
BlockInstance,
BlockDefinition,
IDENTITY_TRANSFORM,
BlockDefinition,
BlockInstance,
Transform,
)
+88
View File
@@ -0,0 +1,88 @@
from enum import Enum, IntEnum
from typing import Any, Dict, List, Optional, Tuple
import pytest
from specklepy.objects.base import Base, _validate_type
from specklepy.objects.primitive import Interval
test_base = Base()
class FakeEnum(Enum):
foo = "foo"
bar = "bar"
class FakeIntEnum(IntEnum):
one = 1
@pytest.mark.parametrize(
"input_type, value, is_valid, return_value",
[
(str, 10, True, "10"),
(str, "foo_bar", True, "foo_bar"),
(
str,
{"foo": "bar"},
True,
"{'foo': 'bar'}",
),
(float, 1, True, 1),
# why are we allowing this??? We're lying to our users and ourselves too.
(str, None, True, None),
(bool, None, True, None),
# any value is allowed for Any
(Any, "foo", True, "foo"),
(Any, test_base, True, test_base),
# any value is allowed for None as a type. Why is none as a type allowed?
(None, True, True, True),
(None, "True", True, "True"),
(None, {"foo": 1}, True, {"foo": 1}),
(FakeEnum, FakeEnum.bar, True, FakeEnum.bar),
(FakeEnum, FakeEnum.bar.value, True, FakeEnum.bar),
(FakeEnum, "baz", False, "baz"),
(FakeIntEnum, FakeIntEnum.one.value, True, FakeIntEnum.one),
(FakeIntEnum, FakeIntEnum.one, True, FakeIntEnum.one),
(FakeIntEnum, 2, False, 2),
(FakeIntEnum, 123.0, False, 123.0),
(Base, test_base, True, test_base),
(Base, 123, False, 123),
(Optional[int], 1, True, 1),
# this is just silly...
(Optional[int], [1, 2, 3], False, [1, 2, 3]),
(Optional[int], None, True, None),
(Optional[FakeEnum], None, True, None),
(Optional[FakeEnum], FakeEnum.bar, True, FakeEnum.bar),
(Optional[FakeEnum], FakeEnum.bar.value, True, FakeEnum.bar),
(Optional[FakeEnum], "baz", False, "baz"),
(Optional[Base], test_base, True, test_base),
(Optional[Base], None, True, None),
(List[int], [1, 2], True, [1, 2]),
(List[int], ["1", 2], False, ["1", 2]),
# same as the dict typing below...
(List[int], [None, 2], True, [None, 2]),
(List[Optional[int]], [None, 2], True, [None, 2]),
(Dict[str, int], {"foo": 1}, True, {"foo": 1}),
(Dict[str, Optional[int]], {"foo": None}, True, {"foo": None}),
# this case should be
# (Dict[int, Base], {1: None}, False, {1: None}),
# but type checking currently allows everything to be None
(Dict[int, Base], {1: None}, True, {1: None}),
(Dict[int, Base], {1: test_base}, True, {1: test_base}),
(Tuple[int, str, str], (1, "foo", "bar"), True, (1, "foo", "bar")),
# given our current rules, this is the reality. Its just sad...
(Tuple[str, str, str], (1, "foo", "bar"), True, ("1", "foo", "bar")),
(Tuple[str, Optional[str], str], (1, None, "bar"), True, ("1", None, "bar")),
],
)
def test_validate_type(
input_type: type, value: Any, is_valid: bool, return_value: Any
) -> None:
assert (is_valid, return_value) == _validate_type(input_type, value)
def test_intervar_type():
i = Interval(start=5, end=10)
assert i
+4 -2
View File
@@ -1,4 +1,5 @@
import pytest
from specklepy.api.client import SpeckleClient
from specklepy.api.models import Activity, ActivityCollection, User
from specklepy.logging.exceptions import SpeckleException
@@ -18,7 +19,9 @@ class TestUser:
def test_user_search(self, client, second_user_dict):
with pytest.deprecated_call():
search_results = client.user.search(search_query=second_user_dict["name"][:5])
search_results = client.user.search(
search_query=second_user_dict["name"][:5]
)
assert isinstance(search_results, list)
assert isinstance(search_results[0], User)
@@ -49,7 +52,6 @@ class TestUser:
updated = client.user.update(bio=bio)
assert updated is True
with pytest.deprecated_call():
me = client.user.get()
assert me.bio == bio
+5 -3
View File
@@ -1,10 +1,12 @@
import json
from specklepy.api.wrapper import StreamWrapper
from specklepy.transports.sqlite import SQLiteTransport
from specklepy.paths import accounts_path
from pathlib import Path
import pytest
from specklepy.api.wrapper import StreamWrapper
from specklepy.paths import accounts_path
from specklepy.transports.sqlite import SQLiteTransport
def test_parse_stream():
wrap = StreamWrapper("https://testing.speckle.dev/streams/a75ab4f10f")