diff --git a/.gitignore b/.gitignore index 35b9079..5fde443 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +.tool-versions + # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] diff --git a/pyproject.toml b/pyproject.toml index acb53f2..a931b18 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "specklepy" -version = "2.1.0" +version = "2.2.0" description = "The Python SDK for Speckle 2.0" readme = "README.md" authors = ["Speckle Systems "] diff --git a/specklepy/api/credentials.py b/specklepy/api/credentials.py index ae72d5b..3bdc188 100644 --- a/specklepy/api/credentials.py +++ b/specklepy/api/credentials.py @@ -227,4 +227,4 @@ class StreamWrapper: """ if not self.client or not self.client.me: self.get_client(token) - return ServerTransport(self.stream_id, self.client) \ No newline at end of file + return ServerTransport(self.stream_id, self.client) diff --git a/specklepy/api/resources/commit.py b/specklepy/api/resources/commit.py index 7b8e0cb..3d3efe5 100644 --- a/specklepy/api/resources/commit.py +++ b/specklepy/api/resources/commit.py @@ -185,3 +185,40 @@ class Resource(ResourceBase): return self.make_request( query=query, params=params, return_type="commitDelete", parse_response=False ) + + def received( + self, + stream_id: str, + commit_id: str, + source_application: str = "python", + message: Optional[str] = None, + ) -> bool: + """ + Mark a commit object a received by the source application. + """ + query = gql( + """ + mutation CommitReceive($receivedInput:CommitReceivedInput!){ + commitReceive(input:$receivedInput) + } + """ + ) + params = { + "receivedInput": { + "sourceApplication": source_application, + "streamId": stream_id, + "commitId": commit_id, + "message": "message", + } + } + + try: + return self.make_request( + query=query, + params=params, + return_type="commitReceive", + parse_response=False, + ) + except Exception as ex: + print(ex.with_traceback) + return False diff --git a/specklepy/logging/exceptions.py b/specklepy/logging/exceptions.py index 5c690e0..1f6adf8 100644 --- a/specklepy/logging/exceptions.py +++ b/specklepy/logging/exceptions.py @@ -32,4 +32,4 @@ class GraphQLException(SpeckleException): class SpeckleWarning(Warning): def __init__(self, *args: object) -> None: - super().__init__(*args) \ No newline at end of file + super().__init__(*args) diff --git a/specklepy/logging/metrics.py b/specklepy/logging/metrics.py index 44a191e..89c688d 100644 --- a/specklepy/logging/metrics.py +++ b/specklepy/logging/metrics.py @@ -122,4 +122,4 @@ class MetricsTracker(metaclass=Singleton): except Exception as ex: LOG.error("Error sending metrics request: " + str(ex)) - self.queue.task_done() \ No newline at end of file + self.queue.task_done() diff --git a/tests/test_commit.py b/tests/test_commit.py index ef95191..ce22237 100644 --- a/tests/test_commit.py +++ b/tests/test_commit.py @@ -68,3 +68,20 @@ class TestCommit: deleted = client.commit.delete(stream_id=stream.id, commit_id=commit_id) assert deleted is True + + def test_commit_marked_as_received(self, client, stream, mesh) -> None: + commit = Commit(message="this commit should be received") + commit.id = client.commit.create( + stream_id=stream.id, + object_id=mesh.id, + message=commit.message, + ) + + commit_marked_received = client.commit.received( + stream.id, + commit.id, + source_application="pytest", + message="testing received", + ) + + assert commit_marked_received == True diff --git a/tests/test_geometry.py b/tests/test_geometry.py index 673930e..2674128 100644 --- a/tests/test_geometry.py +++ b/tests/test_geometry.py @@ -5,11 +5,28 @@ import pytest from specklepy.api import operations from specklepy.objects.base import Base from specklepy.objects.encoding import CurveArray, ObjectArray -from specklepy.objects.geometry import (Arc, Box, Brep, BrepEdge, BrepFace, - BrepLoop, BrepTrim, BrepTrimTypeEnum, - Circle, Curve, Ellipse, Interval, Line, - Mesh, Plane, Point, Polycurve, - Polyline, Surface, Vector) +from specklepy.objects.geometry import ( + Arc, + Box, + Brep, + BrepEdge, + BrepFace, + BrepLoop, + BrepTrim, + BrepTrimTypeEnum, + Circle, + Curve, + Ellipse, + Interval, + Line, + Mesh, + Plane, + Point, + Polycurve, + Polyline, + Surface, + Vector, +) from specklepy.transports.memory import MemoryTransport @@ -71,7 +88,7 @@ def arc(plane, interval): angleRadians=33, plane=plane, domain=interval, - units='m', + units="m", # These attributes are not handled in C# # bbox=None, # area=None, @@ -88,7 +105,7 @@ def circle(plane, interval): radius=22, plane=plane, domain=interval, - units='m', + units="m", # These attributes are not handled in C# # bbox=None, # area=None, @@ -103,7 +120,7 @@ def ellipse(plane, interval): secondRadius=22, plane=plane, domain=interval, - units='m', + units="m", # These attributes are not handled in C# # trimDomain=None, # bbox=None, @@ -118,7 +135,7 @@ def polyline(interval): value=[22, 44, 54.3, 99, 232, 21], closed=True, domain=interval, - units='m', + units="m", # These attributes are not handled in C# # bbox=None, # area=None, @@ -137,7 +154,7 @@ def curve(interval): points=[23, 21, 44, 43, 56, 76, 1, 3, 2], weights=[23, 11, 23], knots=[22, 45, 76, 11], - units='m', + units="m", # These attributes are not handled in C# # displayValue=None, # bbox=None, @@ -152,7 +169,7 @@ def polycurve(interval, curve, polyline): segments=[curve, polyline], domain=interval, closed=True, - units='m', + units="m", # These attributes are not handled in C# # bbox=None, # area=None, @@ -187,7 +204,7 @@ def surface(interval): domainV=interval, knotsU=[1.1, 2.2, 3.3, 4.4], knotsV=[9, 8, 7, 6, 5, 4.4], - units='m', + units="m", # These attributes are not handled in C# # bbox=None, # area=None, @@ -218,11 +235,7 @@ def brep_edge(interval): @pytest.fixture() def brep_loop(): - return BrepLoop( - FaceIndex=5, - TrimIndices=[3, 4, 5], - Type='unknown' - ) + return BrepLoop(FaceIndex=5, TrimIndices=[3, 4, 5], Type="unknown") @pytest.fixture() @@ -235,7 +248,7 @@ def brep_trim(): LoopIndex=4, CurveIndex=7, IsoStatus=6, - TrimType='Mated', + TrimType="Mated", IsReversed=False, # These attributes are not handled in C# # Domain=None, @@ -243,10 +256,21 @@ def brep_trim(): @pytest.fixture -def brep(mesh, box, surface, curve, polyline, circle, point, - brep_edge, brep_loop, brep_trim, brep_face): +def brep( + mesh, + box, + surface, + curve, + polyline, + circle, + point, + brep_edge, + brep_loop, + brep_trim, + brep_face, +): return Brep( - provenance='pytest', + provenance="pytest", bbox=box, area=32, volume=54, @@ -265,33 +289,57 @@ def brep(mesh, box, surface, curve, polyline, circle, point, @pytest.fixture -def geometry_objects_dict(point, vector, plane, line, arc, - circle, ellipse, polyline, curve, - polycurve, surface, brep_trim): +def geometry_objects_dict( + point, + vector, + plane, + line, + arc, + circle, + ellipse, + polyline, + curve, + polycurve, + surface, + brep_trim, +): return { - 'point': point, - 'vector': vector, - 'plane': plane, - 'line': line, - 'arc': arc, - 'circle': circle, - 'ellipse': ellipse, - 'polyline': polyline, - 'curve': curve, - 'polycurve': polycurve, - 'surface': surface, - 'brep_trim': brep_trim + "point": point, + "vector": vector, + "plane": plane, + "line": line, + "arc": arc, + "circle": circle, + "ellipse": ellipse, + "polyline": polyline, + "curve": curve, + "polycurve": polycurve, + "surface": surface, + "brep_trim": brep_trim, } -@pytest.mark.parametrize('object_name', [ - 'point', 'vector', 'plane', 'line', 'arc', 'circle', - 'ellipse', 'polyline', 'curve', 'polycurve', 'surface', 'brep_trim' -]) +@pytest.mark.parametrize( + "object_name", + [ + "point", + "vector", + "plane", + "line", + "arc", + "circle", + "ellipse", + "polyline", + "curve", + "polycurve", + "surface", + "brep_trim", + ], +) def test_to_and_from_list(object_name: str, geometry_objects_dict): object = geometry_objects_dict[object_name] - assert hasattr(object, 'to_list') - assert hasattr(object, 'from_list') + assert hasattr(object, "to_list") + assert hasattr(object, "from_list") chunks = object.to_list() assert isinstance(chunks, list) @@ -306,8 +354,7 @@ def test_brep_surfaces_value_serialization(surface): assert brep.Surfaces == None assert brep.SurfacesValue == None brep.Surfaces = [surface, surface] - assert brep.SurfacesValue == ObjectArray.from_objects( - [surface, surface]).data + assert brep.SurfacesValue == ObjectArray.from_objects([surface, surface]).data brep.SurfacesValue = ObjectArray.from_objects([surface]).data assert len(brep.Surfaces) == 1 @@ -341,16 +388,32 @@ def test_brep_curve3d_values_serialization(curve, polyline, circle): def test_brep_vertices_values_serialization(): brep = Brep() brep.VerticesValue = [1, 1, 1, 1, 2, 2, 2, 3, 3, 3] - brep.Vertices[0].get_id() == Point(x=1, y=1, z=1, _units='mm').get_id() - brep.Vertices[1].get_id() == Point(x=2, y=2, z=2, _units='mm').get_id() - brep.Vertices[2].get_id() == Point(x=3, y=3, z=3, _units='mm').get_id() + brep.Vertices[0].get_id() == Point(x=1, y=1, z=1, _units="mm").get_id() + brep.Vertices[1].get_id() == Point(x=2, y=2, z=2, _units="mm").get_id() + brep.Vertices[2].get_id() == Point(x=3, y=3, z=3, _units="mm").get_id() def test_trims_value_serialization(): brep = Brep() brep.TrimsValue = [ - 0, 0, 0, 0, 0, 0, 1, 1, 1, - 1, 0, 0, 0, 0, 1, 2, 1, 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 1, + 2, + 1, + 0, ] brep.Trims[0].get_id() == BrepTrim( @@ -383,7 +446,7 @@ def test_serialized_brep_attributes(brep: Brep): serialized = operations.serialize(brep, [transport]) serialized_dict = json.loads(serialized) - removed_keys = ['Surfaces', 'Curve3D', 'Curve2D', 'Vertices', 'Trims'] + removed_keys = ["Surfaces", "Curve3D", "Curve2D", "Vertices", "Trims"] for k in removed_keys: assert k not in serialized_dict.keys() diff --git a/tests/test_objects.py b/tests/test_objects.py index d5cd872..1018b71 100644 --- a/tests/test_objects.py +++ b/tests/test_objects.py @@ -21,11 +21,9 @@ class TestObject: def test_object_create(self, client, stream, base): transport = SQLiteTransport() - s = BaseObjectSerializer( - write_transports=[transport], read_transport=transport) + s = BaseObjectSerializer(write_transports=[transport], read_transport=transport) _, base_dict = s.traverse_base(base) - obj_id = client.object.create( - stream_id=stream.id, objects=[base_dict])[0] + obj_id = client.object.create(stream_id=stream.id, objects=[base_dict])[0] assert isinstance(obj_id, str) assert base_dict["@detach"]["speckle_type"] == "reference" @@ -43,12 +41,6 @@ class TestObject: def test_object_array_decoder(self): array = ObjectArray() - array.data = [ - 5, 1, 1, 1, 1, 1, - 4, 1, 1, 1, 1, - 3, 1, 1, 1, - 2, 1, 1, - 1, 1 - ] + array.data = [5, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 3, 1, 1, 1, 2, 1, 1, 1, 1] assert array.decode(decoder=sum) == [5, 4, 3, 2, 1] diff --git a/tests/test_serialization.py b/tests/test_serialization.py index 60d93eb..14be28d 100644 --- a/tests/test_serialization.py +++ b/tests/test_serialization.py @@ -1,5 +1,4 @@ import json -from attr import has import pytest from specklepy.api import operations from specklepy.transports.server import ServerTransport @@ -89,4 +88,4 @@ class TestSerialization: untyped = '{"foo": "bar"}' deserialised = operations.deserialize(untyped) - assert deserialised == {"foo": "bar"} \ No newline at end of file + assert deserialised == {"foo": "bar"}