Compare commits

..

3 Commits

Author SHA1 Message Date
Iain Sproat 9a2651bec1 Specklepy relies on the frontend being available 2024-07-18 08:39:19 +01:00
Iain Sproat a85e3baaec Include toxiproxy.json file 2024-07-17 14:09:07 +01:00
Iain Sproat 9dd801a20b chore(tests): add toxiproxy for integration testing network issues 2024-07-17 13:52:11 +01:00
15 changed files with 541 additions and 871 deletions
+33 -10
View File
@@ -52,26 +52,28 @@ services:
####
# Speckle Server
#######
speckle-frontend:
image: speckle/speckle-frontend-2:latest
image: speckle/speckle-frontend:latest
restart: always
ports:
- "0.0.0.0:8080:8080"
environment:
FILE_SIZE_LIMIT_MB: 100
speckle-server:
image: speckle/speckle-server:latest
restart: always
healthcheck:
test:
- CMD
- /nodejs/bin/node
- -e
- "try { require('node:http').request({headers: {'Content-Type': 'application/json'}, port:3000, hostname:'127.0.0.1', path:'/readiness', method: 'GET', timeout: 2000 }, (res) => { body = ''; res.on('data', (chunk) => {body += chunk;}); res.on('end', () => {process.exit(res.statusCode != 200 || body.toLowerCase().includes('error'));}); }).end(); } catch { process.exit(1); }"
[
"CMD",
"node",
"-e",
"require('node:http').request({headers: {'Content-Type': 'application/json'}, port:3000, hostname:'127.0.0.1', path:'/graphql?query={serverInfo{version}}', method: 'GET' }, (res) => { body = ''; res.on('data', (chunk) => {body += chunk;}); res.on('end', () => {process.exit(res.statusCode != 200 || body.toLowerCase().includes('error'));}); }).end();",
]
interval: 10s
timeout: 10s
retries: 3
start_period: 90s
timeout: 3s
retries: 30
ports:
- "0.0.0.0:3000:3000"
depends_on:
@@ -96,7 +98,6 @@ services:
S3_CREATE_BUCKET: "true"
FILE_SIZE_LIMIT_MB: 100
MAX_PROJECT_MODELS_PER_PAGE: 500
# TODO: Change this to a unique secret for this server
SESSION_SECRET: "TODO:ReplaceWithLongString"
@@ -110,6 +111,28 @@ services:
POSTGRES_DB: "speckle"
ENABLE_MP: "false"
####
# Testing and development tools
#######
toxiproxy:
###
# Toxiproxy is a tool to simulate network conditions https://github.com/Shopify/toxiproxy
# Instead of connecting to speckle-server on port 3000, connect to ToxiProxy on port 3001
# Toxiproxy will forward the connection to speckle-server
# Use the ToxiProxy API to simulate network conditions as necessary
###
image: ghcr.io/shopify/toxiproxy:2.9.0
volumes:
# This mounts the toxiproxy.json file into the container at /config/toxiproxy.json
- ./toxiproxy.json:/config/toxiproxy.json
# This command starts toxiproxy with the configuration file
entrypoint: /toxiproxy -config /config/toxiproxy.json
ports:
# open ports to match the 'listen' ports in the toxiproxy.json file
- 8474:8474 # Toxiproxy API
- 3001:3001 # Speckle server
networks:
default:
name: speckle-server
Generated
+473 -637
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -264,7 +264,7 @@ class AutomationContext:
files = {path_obj.name: open(str(path_obj), "rb")}
url = (
f"{self.automation_run_data.speckle_server_url}api/stream/"
f"{self.automation_run_data.speckle_server_url}/api/stream/"
f"{self.automation_run_data.project_id}/blob"
)
data = (
+3 -3
View File
@@ -21,7 +21,7 @@ class SpeckleClient(CoreSpeckleClient):
The `SpeckleClient` is your entry point for interacting with
your Speckle Server's GraphQL API.
You'll need to have access to a server to use it,
or you can use our public server `app.speckle.systems`.
or you can use our public server `speckle.xyz`.
To authenticate the client, you'll need to have downloaded
the [Speckle Manager](https://speckle.guide/#speckle-manager)
@@ -32,7 +32,7 @@ class SpeckleClient(CoreSpeckleClient):
from specklepy.api.credentials import get_default_account
# initialise the client
client = SpeckleClient(host="app.speckle.systems") # or whatever your host is
client = SpeckleClient(host="speckle.xyz") # 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)
@@ -47,7 +47,7 @@ class SpeckleClient(CoreSpeckleClient):
```
"""
DEFAULT_HOST = "app.speckle.systems"
DEFAULT_HOST = "speckle.xyz"
USE_SSL = True
def __init__(
+1 -1
View File
@@ -22,7 +22,7 @@ class StreamWrapper(CoreStreamWrapper):
from specklepy.api.wrapper import StreamWrapper
# provide any stream, branch, commit, object, or globals url
wrapper = StreamWrapper("https://app.speckle.systems/streams/3073b96e86/commits/604bea8cc6")
wrapper = StreamWrapper("https://speckle.xyz/streams/3073b96e86/commits/604bea8cc6")
# get an authenticated SpeckleClient if you have a local account for the server
client = wrapper.get_client()
+3 -3
View File
@@ -30,7 +30,7 @@ class SpeckleClient:
The `SpeckleClient` is your entry point for interacting with
your Speckle Server's GraphQL API.
You'll need to have access to a server to use it,
or you can use our public server `app.speckle.systems`.
or you can use our public server `speckle.xyz`.
To authenticate the client, you'll need to have downloaded
the [Speckle Manager](https://speckle.guide/#speckle-manager)
@@ -41,7 +41,7 @@ class SpeckleClient:
from specklepy.api.credentials import get_default_account
# initialise the client
client = SpeckleClient(host="app.speckle.systems") # or whatever your host is
client = SpeckleClient(host="speckle.xyz") # 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)
@@ -56,7 +56,7 @@ class SpeckleClient:
```
"""
DEFAULT_HOST = "app.speckle.systems"
DEFAULT_HOST = "speckle.xyz"
USE_SSL = True
def __init__(
+1 -1
View File
@@ -30,7 +30,7 @@ class StreamWrapper:
from specklepy.api.wrapper import StreamWrapper
# provide any stream, branch, commit, object, or globals url
wrapper = StreamWrapper("https://app.speckle.systems/streams/3073b96e86/commits/604bea8cc6")
wrapper = StreamWrapper("https://speckle.xyz/streams/3073b96e86/commits/604bea8cc6")
# get an authenticated SpeckleClient if you have a local account for the server
client = wrapper.get_client()
-18
View File
@@ -1,22 +1,12 @@
"""Builtin Speckle object kit."""
from specklepy.objects.GIS.CRS import CRS
from specklepy.objects.GIS.features import (
GisMultipatchFeature,
GisNonGeometricFeature,
GisPointFeature,
GisPolygonFeature,
GisPolylineFeature,
)
from specklepy.objects.GIS.geometry import (
GisLineElement,
GisPointElement,
GisPolygonElement,
GisPolygonGeometry,
GisRasterElement,
PolygonGeometry,
PolygonGeometry3d,
GisMultipatchGeometry,
)
from specklepy.objects.GIS.layers import RasterLayer, VectorLayer
@@ -24,17 +14,9 @@ __all__ = [
"VectorLayer",
"RasterLayer",
"GisPolygonGeometry",
"PolygonGeometry",
"PolygonGeometry3d",
"GisMultipatchGeometry",
"GisPolygonElement",
"GisLineElement",
"GisPointElement",
"GisRasterElement",
"CRS",
"GisPointFeature",
"GisPolylineFeature",
"GisPolygonFeature",
"GisMultipatchFeature",
"GisNonGeometricFeature",
]
-107
View File
@@ -1,107 +0,0 @@
from typing import List, Optional
from specklepy.objects.base import Base
from specklepy.objects.geometry import Mesh, Point, Polyline
from specklepy.objects.GIS.geometry import PolygonGeometry
class GisNonGeometricFeature(Base, speckle_type="Objects.GIS.GisNonGeometricFeature"):
"""GIS Table feature"""
attributes: Base
def __init__(
self,
attributes: Optional[Base] = None,
) -> None:
self.attributes = attributes or Base()
class GisPointFeature(
Base,
detachable={"displayValue"},
speckle_type="Objects.GIS.GisPointFeature",
):
"""Gis Point Feature"""
attributes: Base
displayValue: List[Point]
@property
def geometry(self) -> List[Point]:
return self.displayValue
def __init__(
self,
attributes: Optional[Base] = None,
displayValue: Optional[List[Point]] = None,
) -> None:
self.attributes = attributes or Base()
displayValue = displayValue or []
class GisPolylineFeature(
Base,
detachable={"displayValue"},
speckle_type="Objects.GIS.GisPolylineFeature",
):
"""Gis Polyline Feature"""
attributes: Base
displayValue: List[Polyline]
@property
def geometry(self) -> List[Polyline]:
return self.displayValue
def __init__(
self,
attributes: Optional[Base] = None,
displayValue: Optional[List[Point]] = None,
) -> None:
self.attributes = attributes or Base()
displayValue = displayValue or []
class GisPolygonFeature(
Base,
detachable={"displayValue", "geometry"},
speckle_type="Objects.GIS.GisPolygonFeature",
):
"""Gis Polygon Feature"""
attributes: Base
displayValue: List[Mesh]
geometry: List[PolygonGeometry]
def __init__(
self,
geometry: List[PolygonGeometry],
attributes: Optional[Base] = None,
displayValue: Optional[List[Point]] = None,
) -> None:
self.geometry = geometry
self.attributes = attributes or Base()
displayValue = displayValue or []
class GisMultipatchFeature(
Base,
detachable={"displayValue", "geometry"},
speckle_type="Objects.GIS.GisMultipatchFeature",
):
"""Gis Multipatch Feature"""
attributes: Base
displayValue: List[Mesh]
geometry: List[Base] # GisMultipatchGeometry or PolygonGeometry3d
def __init__(
self,
geometry: List[Base],
attributes: Optional[Base] = None,
displayValue: Optional[List[Point]] = None,
) -> None:
self.geometry = geometry
self.attributes = attributes or Base()
displayValue = displayValue or []
+7 -57
View File
@@ -1,7 +1,5 @@
from typing import List, Optional, Union
from deprecated import deprecated
from specklepy.objects.base import Base
from specklepy.objects.geometry import (
Arc,
@@ -14,69 +12,23 @@ from specklepy.objects.geometry import (
)
class PolygonGeometry(Base, speckle_type="Objects.GIS.PolygonGeometry"):
class GisPolygonGeometry(
Base, speckle_type="Objects.GIS.PolygonGeometry", detachable={"displayValue"}
):
"""GIS Polygon Geometry"""
boundary: Polyline
voids: List[Polyline]
def __init__(
self,
units: str,
boundary: Polyline,
voids: Optional[List[Polyline]] = None,
) -> None:
super().__init__(units=units)
self.boundary = boundary
self.voids = voids or []
boundary: Optional[Union[Polyline, Arc, Line, Circle, Polycurve]] = None
voids: Optional[List[Union[Polyline, Arc, Line, Circle, Polycurve]]] = None
displayValue: Optional[List[Mesh]] = None
GisPolygonGeometry = PolygonGeometry
class PolygonGeometry3d(
PolygonGeometry,
speckle_type="Objects.GIS.PolygonGeometry3d",
):
"""GIS Polygon3d Geometry"""
def __init__(
self,
units: str,
boundary: Polyline,
voids: Optional[List[Polyline]] = None,
) -> None:
super().__init__(units=units, boundary=boundary, voids=voids)
class GisMultipatchGeometry(
Base,
speckle_type="Objects.GIS.GisMultipatchGeometry",
):
"""GIS Polygon3d Geometry"""
def __init__(
self,
units: str,
faces: List[int],
vertices: List[float],
colors: Optional[List[int]],
) -> None:
super().__init__(units=units)
self.faces = faces
self.vertices = vertices
self.colors = colors or []
@deprecated(version="2.20", reason="Replaced with GisPolygonFeature")
class GisPolygonElement(Base, speckle_type="Objects.GIS.PolygonElement"):
"""GIS Polygon element"""
geometry: Optional[List[PolygonGeometry]] = None
geometry: Optional[List[GisPolygonGeometry]] = None
attributes: Optional[Base] = None
@deprecated(version="2.20", reason="Replaced with GisPolyineFeature")
class GisLineElement(Base, speckle_type="Objects.GIS.LineElement"):
"""GIS Polyline element"""
@@ -84,7 +36,6 @@ class GisLineElement(Base, speckle_type="Objects.GIS.LineElement"):
attributes: Optional[Base] = None
@deprecated(version="2.20", reason="Replaced with GisPointFeature")
class GisPointElement(Base, speckle_type="Objects.GIS.PointElement"):
"""GIS Point element"""
@@ -117,7 +68,6 @@ class GisTopography(
"""GIS Raster element with 3d Topography representation"""
@deprecated(version="2.20", reason="Replaced with GisNonGeometricFeature")
class GisNonGeometryElement(Base, speckle_type="Objects.GIS.NonGeometryElement"):
"""GIS Table feature"""
+3 -19
View File
@@ -295,33 +295,17 @@ class RevitParameter(Base, speckle_type="Objects.BuiltElements.Revit.Parameter")
value: Any = None
applicationUnitType: Optional[str] = None # eg UnitType UT_Length
applicationUnit: Optional[str] = None # DisplayUnitType eg DUT_MILLIMITERS
applicationInternalName: Optional[str] = (
None # BuiltInParameterName or GUID for shared parameter
)
applicationInternalName: Optional[
str
] = None # BuiltInParameterName or GUID for shared parameter
isShared: bool = False
isReadOnly: bool = False
isTypeParameter: bool = False
@deprecated(
version="2.20", reason="Collections namespace changed, collectionType deprecated"
)
class Collection(
Base, speckle_type="Speckle.Core.Models.Collection", detachable={"elements"}
):
name: Optional[str] = None
collectionType: Optional[str] = None
elements: Optional[List[Base]] = None
class Collection( # noqa: F811
Base,
speckle_type="Speckle.Core.Models.Collections.Collection",
detachable={"elements"},
):
name: str
elements: List[Base]
def init(self, name: str, elements: Optional[List[Base]] = None):
self.name = name
self.elements = elements or []
+2 -2
View File
@@ -17,13 +17,13 @@ metrics.disable()
@pytest.fixture(scope="session")
def host():
return "localhost:3000"
return "localhost:3001"
def seed_user(host):
seed = uuid.uuid4().hex
user_dict = {
"email": f"{seed[0:7]}@example.org",
"email": f"{seed[0:7]}@spockle.com",
"password": "$uper$3cr3tP@ss",
"name": f"{seed[0:7]} Name",
"company": "test spockle",
+2 -2
View File
@@ -183,7 +183,7 @@ class TestStream:
# NOTE: only works for server admins
# invited = client.stream.invite_batch(
# stream_id=stream.id,
# emails=["userA@example.org", "userB@example.org"],
# emails=["userA@speckle.xyz", "userB@speckle.xyz"],
# user_ids=[second_user.id],
# message="yeehaw 🤠",
# )
@@ -192,7 +192,7 @@ class TestStream:
# invited_only_email = client.stream.invite_batch(
# stream_id=stream.id,
# emails=["userC@example.org"],
# emails=["userC@speckle.xyz"],
# message="yeehaw 🤠",
# )
+4 -10
View File
@@ -100,20 +100,16 @@ def test_parse_globals_as_commit():
#! NOTE: the following three tests may not pass locally
# if you have a `app.speckle.systems` account in manager
# if you have a `speckle.xyz` account in manager
def test_get_client_without_auth():
wrap = StreamWrapper(
"https://app.speckle.systems/streams/4c3ce1459c/commits/8b9b831792"
)
wrap = StreamWrapper("https://speckle.xyz/streams/4c3ce1459c/commits/8b9b831792")
client = wrap.get_client()
assert client is not None
def test_get_new_client_with_token(user_path):
wrap = StreamWrapper(
"https://app.speckle.systems/streams/4c3ce1459c/commits/8b9b831792"
)
wrap = StreamWrapper("https://speckle.xyz/streams/4c3ce1459c/commits/8b9b831792")
client = wrap.get_client()
client = wrap.get_client(token="super-secret-token")
@@ -121,9 +117,7 @@ def test_get_new_client_with_token(user_path):
def test_get_transport_with_token():
wrap = StreamWrapper(
"https://app.speckle.systems/streams/4c3ce1459c/commits/8b9b831792"
)
wrap = StreamWrapper("https://speckle.xyz/streams/4c3ce1459c/commits/8b9b831792")
client = wrap.get_client()
assert not client.account.token # unauthenticated bc no local accounts
+8
View File
@@ -0,0 +1,8 @@
[
{
"name": "speckle_test_speckle-server",
"listen": "0.0.0.0:3001",
"upstream": "speckle-server:3000",
"enabled": true
}
]