From 457faa103ff38470122cbae9648b3caaf0dc56fd Mon Sep 17 00:00:00 2001 From: Robby Date: Fri, 11 Jul 2025 14:17:14 -0400 Subject: [PATCH 1/2] update pacakge name from py-d2 to d2-python --- README.md | 15 ++-- examples/simple_sql_schema.py | 10 +-- pyproject.toml | 16 ++-- src/d2/__init__.py | 20 +++++ src/{py_d2 => d2}/connection.py | 2 +- src/{py_d2 => d2}/diagram.py | 24 +++--- src/{py_d2 => d2}/helpers.py | 0 src/d2/main.py | 24 ++++++ src/{py_d2 => d2}/py.typed | 0 src/{py_d2 => d2}/shape.py | 30 +++---- src/{py_d2 => d2}/sql_table.py | 18 ++-- src/{py_d2 => d2}/style.py | 4 +- src/py_d2/__init__.py | 20 ----- src/py_d2/main.py | 24 ------ tests/test_py_d2/test_d2_connection.py | 20 ++--- tests/test_py_d2/test_d2_diagram.py | 40 ++++----- tests/test_py_d2/test_d2_layer.py | 36 ++++---- tests/test_py_d2/test_d2_shape.py | 112 ++++++++++++------------- tests/test_py_d2/test_d2_sql_table.py | 22 ++--- tests/test_py_d2/test_d2_style.py | 20 ++--- tests/test_py_d2/test_helpers.py | 2 +- tests/test_py_d2/test_main.py | 2 +- uv.lock | 70 ++++++++-------- 23 files changed, 266 insertions(+), 265 deletions(-) create mode 100644 src/d2/__init__.py rename src/{py_d2 => d2}/connection.py (98%) rename src/{py_d2 => d2}/diagram.py (76%) rename src/{py_d2 => d2}/helpers.py (100%) create mode 100644 src/d2/main.py rename src/{py_d2 => d2}/py.typed (100%) rename src/{py_d2 => d2}/shape.py (85%) rename src/{py_d2 => d2}/sql_table.py (92%) rename src/{py_d2 => d2}/style.py (95%) delete mode 100644 src/py_d2/__init__.py delete mode 100644 src/py_d2/main.py diff --git a/README.md b/README.md index 87504b6..01f19c8 100644 --- a/README.md +++ b/README.md @@ -7,26 +7,25 @@ An unofficial, fully typed python interface for building [.d2](https://github.co ## Installation ```bash -pip install py-d2 +pip install d2-python ``` ## Usage ```python -from py_d2 import D2Diagram, D2Shape, D2Connection, D2Style +import d2 shapes = [ - D2Shape(name="shape_name1", style=D2Style(fill="red")), - D2Shape(name="shape_name2", style=D2Style(fill="blue"))] + d2.Shape(name="shape_name1", style=d2.Style(fill="red")), + d2.Shape(name="shape_name2", style=d2.Style(fill="blue"))] connections = [ - D2Connection(shape_1="shape_name1", shape_2="shape_name2") + d2.Connection(shape_1="shape_name1", shape_2="shape_name2") ] -diagram = D2Diagram(shapes=shapes, connections=connections) +diagram = d2.Diagram(shapes=shapes, connections=connections) with open("graph.d2", "w", encoding="utf-8") as f: f.write(str(diagram)) - ``` produces the following graph.d2 file: @@ -104,7 +103,7 @@ following the steps below to setup the project: ```bash # Clone the repository -git clone git@github.com:MrBlenny/py-d2.git && cd py-d2 +git clone git@github.com:h0rv/d2-python.git && cd d2-python # Install all dependencies uv sync --all-extras --dev diff --git a/examples/simple_sql_schema.py b/examples/simple_sql_schema.py index 161fc39..8ea5221 100644 --- a/examples/simple_sql_schema.py +++ b/examples/simple_sql_schema.py @@ -1,16 +1,16 @@ import os import subprocess -from py_d2.diagram import D2Diagram -from py_d2.sql_table import SQLConstraint -from py_d2.sql_table import SQLTable -from py_d2.sql_table import create_foreign_key_connection +from d2.diagram import Diagram +from d2.sql_table import SQLConstraint +from d2.sql_table import SQLTable +from d2.sql_table import create_foreign_key_connection FILE_NAME = "simple_sql_schema" # Create a new diagram -diagram = D2Diagram() +diagram = Diagram() # Create Users table users = SQLTable("users") diff --git a/pyproject.toml b/pyproject.toml index 9ddd838..f81ec74 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [project] -name = "py-d2" +name = "d2-python" version = "1.1.0" description = "An unofficial, fully typed python interface for building .d2 graph files in python." authors = [ @@ -10,6 +10,7 @@ license = {text = "MIT"} readme = "README.md" requires-python = ">=3.8" keywords = [ + "d2-python", "d2", "py-d2", "d2-lang", @@ -32,12 +33,12 @@ classifiers = [ ] [project.urls] -Repository = "https://github.com/h0rv/py-d2" -Documentation = "https://github.com/h0rv/py-d2/blob/main/README.md" -"Bug Tracker" = "https://github.com/h0rv/py-d2/issues" +Repository = "https://github.com/h0rv/d2-python" +Documentation = "https://github.com/h0rv/d2-python/blob/main/README.md" +"Bug Tracker" = "https://github.com/h0rv/d2-python/issues" [project.scripts] -example = "py_d2.main:example" +example = "d2.main:example" [project.optional-dependencies] dev = [ @@ -56,7 +57,8 @@ coverage = [ [tool.uv] package = true -[tool.uv.sources] +[tool.uv.build-backend] +module-name = "d2" [build-system] requires = ["uv_build>=0.7.19,<0.8.0"] @@ -105,4 +107,4 @@ line-ending = "auto" force-single-line = true force-sort-within-sections = true lines-after-imports = 2 -known-first-party = ["py_d2"] +known-first-party = ["d2"] diff --git a/src/d2/__init__.py b/src/d2/__init__.py new file mode 100644 index 0000000..b41582b --- /dev/null +++ b/src/d2/__init__.py @@ -0,0 +1,20 @@ +from .connection import Connection +from .connection import Direction +from .diagram import Diagram +from .diagram import Layer +from .shape import Shape +from .shape import ShapeType +from .shape import Text +from .style import Style + + +__all__ = [ + "Direction", + "Connection", + "Diagram", + "Shape", + "ShapeType", + "Text", + "Style", + "Layer", +] diff --git a/src/py_d2/connection.py b/src/d2/connection.py similarity index 98% rename from src/py_d2/connection.py rename to src/d2/connection.py index 0206739..ed9cd6d 100644 --- a/src/py_d2/connection.py +++ b/src/d2/connection.py @@ -10,7 +10,7 @@ class Direction(Enum): NONE = "--" -class D2Connection: +class Connection: def __init__(self, shape_1: str, shape_2: str, label: Optional[str] = None, direction: Direction = Direction.TO): self.shape_1 = shape_1 self.shape_2 = shape_2 diff --git a/src/py_d2/diagram.py b/src/d2/diagram.py similarity index 76% rename from src/py_d2/diagram.py rename to src/d2/diagram.py index 96b033e..b761260 100644 --- a/src/py_d2/diagram.py +++ b/src/d2/diagram.py @@ -3,22 +3,22 @@ from typing import List from typing import Optional -from py_d2.connection import D2Connection -from py_d2.helpers import indent -from py_d2.helpers import indent_lines -from py_d2.shape import D2Shape +from d2.connection import Connection +from d2.helpers import indent +from d2.helpers import indent_lines +from d2.shape import Shape class Layer: def __init__( self, name: str, - diagram: Optional[D2Diagram] = None, + diagram: Optional[Diagram] = None, ): self.name = name - self.diagram = diagram or D2Diagram() + self.diagram = diagram or Diagram() - def set_diagram(self, diagram: D2Diagram): + def set_diagram(self, diagram: Diagram): self.diagram = diagram def lines(self, depth=1) -> List[str]: @@ -44,21 +44,21 @@ def __repr__(self) -> str: return "\n".join(lines) -class D2Diagram: +class Diagram: def __init__( self, - shapes: Optional[List[D2Shape]] = None, - connections: Optional[List[D2Connection]] = None, + shapes: Optional[List[Shape]] = None, + connections: Optional[List[Connection]] = None, layers: Optional[List[Layer]] = None, ): self.shapes = shapes or [] self.connections = connections or [] self.layers = layers or [] - def add_shape(self, shape: D2Shape): + def add_shape(self, shape: Shape): self.shapes.append(shape) - def add_connection(self, connection: D2Connection): + def add_connection(self, connection: Connection): self.connections.append(connection) def add_layer(self, layer: Layer): diff --git a/src/py_d2/helpers.py b/src/d2/helpers.py similarity index 100% rename from src/py_d2/helpers.py rename to src/d2/helpers.py diff --git a/src/d2/main.py b/src/d2/main.py new file mode 100644 index 0000000..a4a655f --- /dev/null +++ b/src/d2/main.py @@ -0,0 +1,24 @@ +from d2.connection import Connection +from d2.diagram import Diagram +from d2.shape import Shape +from d2.style import Style + + +def example(): + print("Contructing a simple graph...") + shapes = [ + Shape(name="shape_name1", style=Style(fill="red")), + Shape(name="shape_name2", style=Style(fill="blue")), + ] + connections = [Connection(shape_1="shape_name1", shape_2="shape_name2")] + + diagram = Diagram(shapes=shapes, connections=connections) + + print("Writing graph to file...") + with open("graph.d2", "w", encoding="utf-8") as f: + f.write(str(diagram)) + print("Done! (graph.d2)") + + +if __name__ == "__main__": + example() diff --git a/src/py_d2/py.typed b/src/d2/py.typed similarity index 100% rename from src/py_d2/py.typed rename to src/d2/py.typed diff --git a/src/py_d2/shape.py b/src/d2/shape.py similarity index 85% rename from src/py_d2/shape.py rename to src/d2/shape.py index 2eeb2d9..babc46c 100644 --- a/src/py_d2/shape.py +++ b/src/d2/shape.py @@ -4,14 +4,14 @@ from typing import List from typing import Optional -from py_d2.connection import D2Connection -from py_d2.helpers import add_label_and_properties -from py_d2.helpers import flatten -from py_d2.helpers import indent_lines -from py_d2.style import D2Style +from d2.connection import Connection +from d2.helpers import add_label_and_properties +from d2.helpers import flatten +from d2.helpers import indent_lines +from d2.style import Style -class Shape(Enum): +class ShapeType(Enum): rectangle = "rectangle" square = "square" page = "page" @@ -37,7 +37,7 @@ class Shape(Enum): sequence_diagram = "sequence_diagram" -class D2Text: +class Text: def __init__( self, # The actual text body (multiline is fine) @@ -59,27 +59,27 @@ def __repr__(self) -> str: return "\n".join(self.lines()) -class D2Shape: +class Shape: def __init__( self, name: str, # The label of this shape label: Optional[str] = None, # The actual 2D shape of this shape - shape: Optional[Shape] = None, + shape: Optional[ShapeType] = None, # A list of child shapes (when this shape is a container) - shapes: Optional[List[D2Shape]] = None, + shapes: Optional[List[Shape]] = None, # The style of this shape - style: Optional[D2Style] = None, + style: Optional[Style] = None, # An icon for this shape icon: Optional[str] = None, # Connections for the child shapes (NOT the connections for this shape) - connections: Optional[List[D2Connection]] = None, + connections: Optional[List[Connection]] = None, # A shape this is near near: Optional[str] = None, # A link for a shape (when clicked) link: Optional[str] = None, - **kwargs: D2Text, + **kwargs: Text, ): self.name = name self.label = label @@ -92,10 +92,10 @@ def __init__( self.link = link self.kwargs = kwargs - def add_shape(self, shape: D2Shape): + def add_shape(self, shape: Shape): self.shapes.append(shape) - def add_connection(self, connection: D2Connection): + def add_connection(self, connection: Connection): self.connections.append(connection) def lines(self) -> List[str]: diff --git a/src/py_d2/sql_table.py b/src/d2/sql_table.py similarity index 92% rename from src/py_d2/sql_table.py rename to src/d2/sql_table.py index 905692a..6f8cd6e 100644 --- a/src/py_d2/sql_table.py +++ b/src/d2/sql_table.py @@ -7,10 +7,10 @@ from typing import Optional from typing import Union -from py_d2.connection import D2Connection -from py_d2.connection import Direction -from py_d2.shape import D2Shape -from py_d2.shape import Shape +from d2.connection import Connection +from d2.connection import Direction +from d2.shape import Shape +from d2.shape import ShapeType class SQLConstraint(Enum): @@ -52,7 +52,7 @@ def to_d2_format(self) -> str: return f"{self.name}: {self.data_type} {{constraint: {constraint_part}}}" -class SQLTable(D2Shape): +class SQLTable(Shape): def __init__( self, name: str, @@ -66,7 +66,7 @@ def __init__( super().__init__( name=name, label=label, - shape=Shape.sql_table, + shape=ShapeType.sql_table, style=style, icon=icon, near=near, @@ -135,7 +135,7 @@ def lines(self) -> List[str]: properties.extend(connection_lines) # Create the final lines - from py_d2.helpers import add_label_and_properties + from d2.helpers import add_label_and_properties lines = add_label_and_properties(self.name, self.label, properties) @@ -148,8 +148,8 @@ def create_foreign_key_connection( target_table: str, target_field: str, label: Optional[str] = None, -) -> D2Connection: +) -> Connection: """Create a foreign key connection between two tables.""" source = f"{source_table}.{source_field}" target = f"{target_table}.{target_field}" - return D2Connection(source, target, label, Direction.TO) + return Connection(source, target, label, Direction.TO) diff --git a/src/py_d2/style.py b/src/d2/style.py similarity index 95% rename from src/py_d2/style.py rename to src/d2/style.py index 609fc0d..497b45b 100644 --- a/src/py_d2/style.py +++ b/src/d2/style.py @@ -1,14 +1,14 @@ from typing import List from typing import Optional -from py_d2.helpers import add_label_and_properties +from d2.helpers import add_label_and_properties def stringify_bool(val: bool) -> str: return "true" if val else "false" -class D2Style: +class Style: def __init__( self, stroke: Optional[str] = None, diff --git a/src/py_d2/__init__.py b/src/py_d2/__init__.py deleted file mode 100644 index 409d59f..0000000 --- a/src/py_d2/__init__.py +++ /dev/null @@ -1,20 +0,0 @@ -from .connection import D2Connection -from .connection import Direction -from .diagram import D2Diagram -from .diagram import Layer -from .shape import D2Shape -from .shape import D2Text -from .shape import Shape -from .style import D2Style - - -__all__ = [ - "Direction", - "D2Connection", - "D2Diagram", - "D2Shape", - "D2Text", - "D2Style", - "Shape", - "Layer", -] diff --git a/src/py_d2/main.py b/src/py_d2/main.py deleted file mode 100644 index 3ddf1cd..0000000 --- a/src/py_d2/main.py +++ /dev/null @@ -1,24 +0,0 @@ -from py_d2.connection import D2Connection -from py_d2.diagram import D2Diagram -from py_d2.shape import D2Shape -from py_d2.style import D2Style - - -def example(): - print("Contructing a simple graph...") - shapes = [ - D2Shape(name="shape_name1", style=D2Style(fill="red")), - D2Shape(name="shape_name2", style=D2Style(fill="blue")), - ] - connections = [D2Connection(shape_1="shape_name1", shape_2="shape_name2")] - - diagram = D2Diagram(shapes=shapes, connections=connections) - - print("Writing graph to file...") - with open("graph.d2", "w", encoding="utf-8") as f: - f.write(str(diagram)) - print("Done! (graph.d2)") - - -if __name__ == "__main__": - example() diff --git a/tests/test_py_d2/test_d2_connection.py b/tests/test_py_d2/test_d2_connection.py index d0b041e..35d1125 100644 --- a/tests/test_py_d2/test_d2_connection.py +++ b/tests/test_py_d2/test_d2_connection.py @@ -1,38 +1,38 @@ -from py_d2.connection import D2Connection -from py_d2.connection import Direction +from d2.connection import Connection +from d2.connection import Direction def test_d2_connection_label(): - connection = D2Connection(shape_1="a", shape_2="b", label="c") + connection = Connection(shape_1="a", shape_2="b", label="c") assert str(connection) == "a -> b: c" def test_d2_connection_no_label(): - connection = D2Connection(shape_1="a", shape_2="b") + connection = Connection(shape_1="a", shape_2="b") assert str(connection) == "a -> b" def test_d2_connection_direction_to(): - connection = D2Connection(shape_1="a", shape_2="b", direction=Direction.TO) + connection = Connection(shape_1="a", shape_2="b", direction=Direction.TO) assert str(connection) == "a -> b" def test_d2_connection_direction_from(): - connection = D2Connection(shape_1="a", shape_2="b", direction=Direction.FROM) + connection = Connection(shape_1="a", shape_2="b", direction=Direction.FROM) assert str(connection) == "a <- b" def test_d2_connection_direction_both(): - connection = D2Connection(shape_1="a", shape_2="b", direction=Direction.BOTH) + connection = Connection(shape_1="a", shape_2="b", direction=Direction.BOTH) assert str(connection) == "a <-> b" def test_d2_connection_direction_none(): - connection = D2Connection(shape_1="a", shape_2="b", direction=Direction.NONE) + connection = Connection(shape_1="a", shape_2="b", direction=Direction.NONE) assert str(connection) == "a -- b" def test_d2_connection_uniqueness(): - connection = D2Connection(shape_1="a", shape_2="b", direction=Direction.TO) - connection2 = D2Connection(shape_1="a", shape_2="b", direction=Direction.TO) + connection = Connection(shape_1="a", shape_2="b", direction=Direction.TO) + connection2 = Connection(shape_1="a", shape_2="b", direction=Direction.TO) assert connection == connection2 diff --git a/tests/test_py_d2/test_d2_diagram.py b/tests/test_py_d2/test_d2_diagram.py index 0f8639a..e8d9d3b 100644 --- a/tests/test_py_d2/test_d2_diagram.py +++ b/tests/test_py_d2/test_d2_diagram.py @@ -1,50 +1,50 @@ -from py_d2.connection import D2Connection -from py_d2.diagram import D2Diagram -from py_d2.shape import D2Shape -from py_d2.style import D2Style +from d2.connection import Connection +from d2.diagram import Diagram +from d2.shape import Shape +from d2.style import Style def test_d2_diagram(): - diagram = D2Diagram() + diagram = Diagram() assert str(diagram) == "" def test_d2_diagram_one_shape(): - diagram = D2Diagram() - diagram.add_shape(D2Shape(name="shape_name")) + diagram = Diagram() + diagram.add_shape(Shape(name="shape_name")) assert str(diagram) == "shape_name" def test_d2_diagram_two_shapes(): - shapes = [D2Shape(name="shape_name1"), D2Shape(name="shape_name2")] - diagram = D2Diagram(shapes=shapes) + shapes = [Shape(name="shape_name1"), Shape(name="shape_name2")] + diagram = Diagram(shapes=shapes) assert str(diagram) == "\n".join(["shape_name1", "shape_name2"]) def test_d2_diagram_one_connection(): - shapes = [D2Shape(name="shape_name1"), D2Shape(name="shape_name2")] - connections = [D2Connection(shape_1="shape_name1", shape_2="shape_name2")] + shapes = [Shape(name="shape_name1"), Shape(name="shape_name2")] + connections = [Connection(shape_1="shape_name1", shape_2="shape_name2")] - diagram = D2Diagram(shapes=shapes, connections=connections) + diagram = Diagram(shapes=shapes, connections=connections) assert str(diagram) == "\n".join(["shape_name1", "shape_name2", "shape_name1 -> shape_name2"]) def test_d2_diagram_one_connection_imperative_connection(): - diagram = D2Diagram() - diagram.add_shape(D2Shape(name="shape_name1")) - diagram.add_shape(D2Shape(name="shape_name2")) - diagram.add_connection(D2Connection(shape_1="shape_name1", shape_2="shape_name2")) + diagram = Diagram() + diagram.add_shape(Shape(name="shape_name1")) + diagram.add_shape(Shape(name="shape_name2")) + diagram.add_connection(Connection(shape_1="shape_name1", shape_2="shape_name2")) assert str(diagram) == "\n".join(["shape_name1", "shape_name2", "shape_name1 -> shape_name2"]) def test_d2_diagram_one_connection_with_style(): shapes = [ - D2Shape(name="shape_name1", style=D2Style(fill="red")), - D2Shape(name="shape_name2", style=D2Style(fill="blue")), + Shape(name="shape_name1", style=Style(fill="red")), + Shape(name="shape_name2", style=Style(fill="blue")), ] - connections = [D2Connection(shape_1="shape_name1", shape_2="shape_name2")] + connections = [Connection(shape_1="shape_name1", shape_2="shape_name2")] - diagram = D2Diagram(shapes=shapes, connections=connections) + diagram = Diagram(shapes=shapes, connections=connections) assert str(diagram) == "\n".join( [ "shape_name1: {", diff --git a/tests/test_py_d2/test_d2_layer.py b/tests/test_py_d2/test_d2_layer.py index ecfd8b2..8cab16e 100644 --- a/tests/test_py_d2/test_d2_layer.py +++ b/tests/test_py_d2/test_d2_layer.py @@ -1,24 +1,24 @@ -from py_d2.connection import D2Connection -from py_d2.diagram import D2Diagram -from py_d2.diagram import Layer +from d2.connection import Connection +from d2.diagram import Diagram +from d2.diagram import Layer def test_d2_layer(): layer = Layer(name="my_layer") - diagram = D2Diagram(layers=[layer]) + diagram = Diagram(layers=[layer]) assert str(diagram) == "" def test_d2_layer_single_subdiagram(): """Test a root diagram with a connection and a single layer containing its own connection.""" - root_connection = D2Connection(shape_1="x", shape_2="y") + root_connection = Connection(shape_1="x", shape_2="y") - layer_connection = D2Connection(shape_1="1", shape_2="2") - layer_diagram = D2Diagram(connections=[layer_connection]) + layer_connection = Connection(shape_1="1", shape_2="2") + layer_diagram = Diagram(connections=[layer_connection]) layer = Layer(name="numbers", diagram=layer_diagram) - root_diagram = D2Diagram(connections=[root_connection], layers=[layer]) + root_diagram = Diagram(connections=[root_connection], layers=[layer]) expected_output = "x -> y\nlayers: {\n numbers: {\n 1 -> 2\n }\n}" @@ -27,30 +27,30 @@ def test_d2_layer_single_subdiagram(): def test_d2_layer_two_layers_depth_1(): """Test diagram with two layers at depth 1""" - connection1 = D2Connection(shape_1="a", shape_2="b") - layer1_diagram = D2Diagram(connections=[connection1]) + connection1 = Connection(shape_1="a", shape_2="b") + layer1_diagram = Diagram(connections=[connection1]) layer1 = Layer(name="layer1", diagram=layer1_diagram) - connection2 = D2Connection(shape_1="c", shape_2="d") - layer2_diagram = D2Diagram(connections=[connection2]) + connection2 = Connection(shape_1="c", shape_2="d") + layer2_diagram = Diagram(connections=[connection2]) layer2 = Layer(name="layer2", diagram=layer2_diagram) - root_diagram = D2Diagram(layers=[layer1, layer2]) + root_diagram = Diagram(layers=[layer1, layer2]) expected_output = "layers: {\n layer1: {\n a -> b\n }\n layer2: {\n c -> d\n }\n}" assert str(root_diagram) == expected_output def test_d2_layer_nested_layer_depth_2(): """Test diagram with a layer nested inside another layer (depth 2)""" - inner_connection = D2Connection(shape_1="e", shape_2="f") - inner_diagram = D2Diagram(connections=[inner_connection]) + inner_connection = Connection(shape_1="e", shape_2="f") + inner_diagram = Diagram(connections=[inner_connection]) inner_layer = Layer(name="inner_layer", diagram=inner_diagram) - outer_connection = D2Connection(shape_1="g", shape_2="h") - outer_diagram = D2Diagram(connections=[outer_connection], layers=[inner_layer]) + outer_connection = Connection(shape_1="g", shape_2="h") + outer_diagram = Diagram(connections=[outer_connection], layers=[inner_layer]) outer_layer = Layer(name="outer_layer", diagram=outer_diagram) - root_diagram = D2Diagram(layers=[outer_layer]) + root_diagram = Diagram(layers=[outer_layer]) expected_output = ( "layers: {\n" " outer_layer: {\n" diff --git a/tests/test_py_d2/test_d2_shape.py b/tests/test_py_d2/test_d2_shape.py index e7a18f7..72a9785 100644 --- a/tests/test_py_d2/test_d2_shape.py +++ b/tests/test_py_d2/test_d2_shape.py @@ -1,45 +1,45 @@ -from py_d2.connection import D2Connection -from py_d2.shape import D2Shape -from py_d2.shape import D2Text -from py_d2.shape import Shape -from py_d2.style import D2Style +from d2.connection import Connection +from d2.shape import Shape +from d2.shape import ShapeType +from d2.shape import Text +from d2.style import Style def test_d2_shape(): - shape = D2Shape(name="shape_name") + shape = Shape(name="shape_name") assert str(shape) == "shape_name" def test_d2_shape_label(): - shape = D2Shape(name="shape_name", label="shape_label") + shape = Shape(name="shape_name", label="shape_label") assert str(shape) == "shape_name: shape_label" def test_d2_shape_empty_label(): - shape = D2Shape(name="shape_name", label="") + shape = Shape(name="shape_name", label="") assert str(shape) == 'shape_name: ""' def test_d2_shape_style(): - shape = D2Shape(name="shape_name", style=D2Style(fill="red")) + shape = Shape(name="shape_name", style=Style(fill="red")) assert str(shape) == "shape_name: {\n style: {\n fill: red\n }\n}" def test_d2_shape_container(): - shape = D2Shape(name="shape_name", label="container_label") - shape.add_shape(D2Shape(name="shape_1")) - shape.add_shape(D2Shape(name="shape_2")) - shape.add_connection(D2Connection(shape_1="shape_1", shape_2="shape_2")) + shape = Shape(name="shape_name", label="container_label") + shape.add_shape(Shape(name="shape_1")) + shape.add_shape(Shape(name="shape_2")) + shape.add_connection(Connection(shape_1="shape_1", shape_2="shape_2")) assert str(shape) == "\n".join( ["shape_name: container_label {", " shape_1", " shape_2", " shape_1 -> shape_2", "}"] ) def test_d2_shape_container_style(): - shape = D2Shape(name="shape_name", label="container_label") - shape.add_shape(D2Shape(name="shape_1", style=D2Style(fill="red"))) - shape.add_shape(D2Shape(name="shape_2")) - shape.add_connection(D2Connection(shape_1="shape_1", shape_2="shape_2")) + shape = Shape(name="shape_name", label="container_label") + shape.add_shape(Shape(name="shape_1", style=Style(fill="red"))) + shape.add_shape(Shape(name="shape_2")) + shape.add_connection(Connection(shape_1="shape_1", shape_2="shape_2")) assert str(shape) == "\n".join( [ @@ -57,16 +57,16 @@ def test_d2_shape_container_style(): def test_d2_shape_container_in_container_with_shapes(): - shape = D2Shape(name="shape_name", label="container_label") + shape = Shape(name="shape_name", label="container_label") shape.add_shape( - D2Shape( + Shape( name="shape_1", - style=D2Style(fill="red"), - shapes=[D2Shape(name="shape_2", style=D2Style(fill="blue")), D2Shape(name="shape_3")], - connections=[D2Connection(shape_1="shape_2", shape_2="shape_3")], + style=Style(fill="red"), + shapes=[Shape(name="shape_2", style=Style(fill="blue")), Shape(name="shape_3")], + connections=[Connection(shape_1="shape_2", shape_2="shape_3")], ) ) - shape.add_shape(D2Shape(name="shape_4")) + shape.add_shape(Shape(name="shape_4")) assert str(shape) == "\n".join( [ @@ -90,30 +90,30 @@ def test_d2_shape_container_in_container_with_shapes(): def test_d2_shape_shapes(): - shape_rectangle = D2Shape(name="shape_name", shape=Shape.rectangle) - shape_rectangle = D2Shape(name="shape_name", shape=Shape.rectangle) - shape_square = D2Shape(name="shape_name", shape=Shape.square) - shape_page = D2Shape(name="shape_name", shape=Shape.page) - shape_parallelogram = D2Shape(name="shape_name", shape=Shape.parallelogram) - shape_document = D2Shape(name="shape_name", shape=Shape.document) - shape_cylinder = D2Shape(name="shape_name", shape=Shape.cylinder) - shape_queue = D2Shape(name="shape_name", shape=Shape.queue) - shape_package = D2Shape(name="shape_name", shape=Shape.package) - shape_step = D2Shape(name="shape_name", shape=Shape.step) - shape_callout = D2Shape(name="shape_name", shape=Shape.callout) - shape_stored_data = D2Shape(name="shape_name", shape=Shape.stored_data) - shape_person = D2Shape(name="shape_name", shape=Shape.person) - shape_diamond = D2Shape(name="shape_name", shape=Shape.diamond) - shape_oval = D2Shape(name="shape_name", shape=Shape.oval) - shape_circle = D2Shape(name="shape_name", shape=Shape.circle) - shape_hexagon = D2Shape(name="shape_name", shape=Shape.hexagon) - shape_cloud = D2Shape(name="shape_name", shape=Shape.cloud) - shape_text = D2Shape(name="shape_name", shape=Shape.text) - shape_code = D2Shape(name="shape_name", shape=Shape.code) - shape_sql_table = D2Shape(name="shape_name", shape=Shape.sql_table) - shape_image = D2Shape(name="shape_name", shape=Shape.image) - shape_classs = D2Shape(name="shape_name", shape=Shape.classs) - shape_sequence_diagram = D2Shape(name="shape_name", shape=Shape.sequence_diagram) + shape_rectangle = Shape(name="shape_name", shape=ShapeType.rectangle) + shape_rectangle = Shape(name="shape_name", shape=ShapeType.rectangle) + shape_square = Shape(name="shape_name", shape=ShapeType.square) + shape_page = Shape(name="shape_name", shape=ShapeType.page) + shape_parallelogram = Shape(name="shape_name", shape=ShapeType.parallelogram) + shape_document = Shape(name="shape_name", shape=ShapeType.document) + shape_cylinder = Shape(name="shape_name", shape=ShapeType.cylinder) + shape_queue = Shape(name="shape_name", shape=ShapeType.queue) + shape_package = Shape(name="shape_name", shape=ShapeType.package) + shape_step = Shape(name="shape_name", shape=ShapeType.step) + shape_callout = Shape(name="shape_name", shape=ShapeType.callout) + shape_stored_data = Shape(name="shape_name", shape=ShapeType.stored_data) + shape_person = Shape(name="shape_name", shape=ShapeType.person) + shape_diamond = Shape(name="shape_name", shape=ShapeType.diamond) + shape_oval = Shape(name="shape_name", shape=ShapeType.oval) + shape_circle = Shape(name="shape_name", shape=ShapeType.circle) + shape_hexagon = Shape(name="shape_name", shape=ShapeType.hexagon) + shape_cloud = Shape(name="shape_name", shape=ShapeType.cloud) + shape_text = Shape(name="shape_name", shape=ShapeType.text) + shape_code = Shape(name="shape_name", shape=ShapeType.code) + shape_sql_table = Shape(name="shape_name", shape=ShapeType.sql_table) + shape_image = Shape(name="shape_name", shape=ShapeType.image) + shape_classs = Shape(name="shape_name", shape=ShapeType.classs) + shape_sequence_diagram = Shape(name="shape_name", shape=ShapeType.sequence_diagram) assert str(shape_rectangle) == "shape_name: {\n shape: rectangle\n}" assert str(shape_rectangle) == "shape_name: {\n shape: rectangle\n}" @@ -142,29 +142,29 @@ def test_d2_shape_shapes(): def test_d2_shape_icon(): - shape = D2Shape(name="shape_name", icon="https://icons.terrastruct.com/essentials%2F117-database.svg") + shape = Shape(name="shape_name", icon="https://icons.terrastruct.com/essentials%2F117-database.svg") assert str(shape) == "shape_name: {\n icon: https://icons.terrastruct.com/essentials%2F117-database.svg\n}" def test_d2_shape_near(): - shape = D2Shape(name="shape_name", near="some_other_shape") + shape = Shape(name="shape_name", near="some_other_shape") assert str(shape) == "shape_name: {\n near: some_other_shape\n}" def test_d2_shape_link(): - shape = D2Shape(name="shape_name", link="https://github.com/MrBlenny/py-d2") + shape = Shape(name="shape_name", link="https://github.com/MrBlenny/py-d2") assert str(shape) == "shape_name: {\n link: https://github.com/MrBlenny/py-d2\n}" def test_d2_shape_other_properties(): text = "Some text" - shape = D2Shape(name="shape_name", thing=D2Text(text=text, formatting="md")) + shape = Shape(name="shape_name", thing=Text(text=text, formatting="md")) assert str(shape) == "\n".join(["shape_name: {", " thing: |md", " Some text", " |", "}"]) def test_d2_shape_other_properties_multi_line(): text = "\n".join(["multiline text", "like this", "works too"]) - shape = D2Shape(name="shape_name", thing=D2Text(text=text, formatting="md")) + shape = Shape(name="shape_name", thing=Text(text=text, formatting="md")) assert str(shape) == "\n".join( ["shape_name: {", " thing: |md", " multiline text", " like this", " works too", " |", "}"] ) @@ -172,10 +172,10 @@ def test_d2_shape_other_properties_multi_line(): def test_d2_shape_other_properties_can_be_anything(): text = "\n".join(["multiline text", "like this", "works too"]) - shape = D2Shape( + shape = Shape( name="shape_name", - description=D2Text(text=text, formatting="md"), - other_thing=D2Text(text=text, formatting="md"), + description=Text(text=text, formatting="md"), + other_thing=Text(text=text, formatting="md"), ) assert str(shape) == "\n".join( [ @@ -197,7 +197,7 @@ def test_d2_shape_other_properties_can_be_anything(): def test_d2_shape_text_can_specify_pipe_count(): text = "const iLoveTypescript = 1 || true;\nconst really = () => iLoveTypescript" - shape = D2Shape(name="shape_name", code=D2Text(text=text, formatting="ts", pipes=3)) + shape = Shape(name="shape_name", code=Text(text=text, formatting="ts", pipes=3)) assert str(shape) == "\n".join( [ "shape_name: {", diff --git a/tests/test_py_d2/test_d2_sql_table.py b/tests/test_py_d2/test_d2_sql_table.py index c0f7b36..5aafa1f 100644 --- a/tests/test_py_d2/test_d2_sql_table.py +++ b/tests/test_py_d2/test_d2_sql_table.py @@ -1,11 +1,11 @@ -from py_d2.connection import Direction -from py_d2.diagram import D2Diagram -from py_d2.shape import D2Shape -from py_d2.sql_table import SQLConstraint -from py_d2.sql_table import SQLField -from py_d2.sql_table import SQLTable -from py_d2.sql_table import create_foreign_key_connection -from py_d2.style import D2Style +from d2.connection import Direction +from d2.diagram import Diagram +from d2.shape import Shape +from d2.sql_table import SQLConstraint +from d2.sql_table import SQLField +from d2.sql_table import SQLTable +from d2.sql_table import create_foreign_key_connection +from d2.style import Style def test_sql_field_simple(): @@ -86,7 +86,7 @@ def test_sql_table_with_fields_dict(): def test_sql_table_with_label_and_style(): """Test creating a SQL table with a label and style.""" - table = SQLTable("users", label="User Table", style=D2Style(fill="lightblue")) + table = SQLTable("users", label="User Table", style=Style(fill="lightblue")) table.add_field("id", "int", SQLConstraint.PRIMARY_KEY) expected = "\n".join( @@ -137,7 +137,7 @@ def test_complex_sql_table_relationship(): # Create connection fk = create_foreign_key_connection("orders", "user_id", "users", "id") - diagram = D2Diagram() + diagram = Diagram() diagram.add_shape(users) diagram.add_shape(orders) diagram.add_connection(fk) @@ -166,7 +166,7 @@ def test_nested_sql_tables(): """Test creating nested SQL tables within a container.""" # Create container - cloud = D2Shape("cloud", label="Cloud Infrastructure") + cloud = Shape("cloud", label="Cloud Infrastructure") # Create SQL tables disks = SQLTable("disks") diff --git a/tests/test_py_d2/test_d2_style.py b/tests/test_py_d2/test_d2_style.py index ec04fea..51d3b68 100644 --- a/tests/test_py_d2/test_d2_style.py +++ b/tests/test_py_d2/test_d2_style.py @@ -1,48 +1,48 @@ -from py_d2.style import D2Style +from d2.style import Style def test_d2_style(): - style = D2Style() + style = Style() assert str(style) == "" def test_d2_style_fill(): - style = D2Style(fill="red") + style = Style(fill="red") assert str(style) == "style: {\n fill: red\n}" def test_d2_style_stroke(): - style = D2Style(stroke="red") + style = Style(stroke="red") assert str(style) == "style: {\n stroke: red\n}" def test_d2_style_stroke_width(): - style = D2Style(stroke_width=2) + style = Style(stroke_width=2) assert str(style) == "style: {\n stroke-width: 2\n}" def test_d2_style_shadow(): - style = D2Style(shadow=True) + style = Style(shadow=True) assert str(style) == "style: {\n shadow: true\n}" def test_d2_style_opacity(): - style = D2Style(opacity=0.5) + style = Style(opacity=0.5) assert str(style) == "style: {\n opacity: 0.5\n}" def test_d2_style_stroke_dash(): - style = D2Style(stroke_dash=2) + style = Style(stroke_dash=2) assert str(style) == "style: {\n stroke-dash: 2\n}" def test_d2_style_three_d(): - style = D2Style(three_d=True) + style = Style(three_d=True) assert str(style) == "style: {\n 3d: true\n}" def test_d2_style_all(): - style = D2Style( + style = Style( stroke="red", stroke_width=2, fill="red", diff --git a/tests/test_py_d2/test_helpers.py b/tests/test_py_d2/test_helpers.py index f7a8d75..afe2ef3 100644 --- a/tests/test_py_d2/test_helpers.py +++ b/tests/test_py_d2/test_helpers.py @@ -1,4 +1,4 @@ -from py_d2.helpers import add_label_and_properties +from d2.helpers import add_label_and_properties def test_add_label_and_properties(): diff --git a/tests/test_py_d2/test_main.py b/tests/test_py_d2/test_main.py index e83749a..ae2d53e 100644 --- a/tests/test_py_d2/test_main.py +++ b/tests/test_py_d2/test_main.py @@ -1,4 +1,4 @@ -from py_d2.main import example +from d2.main import example def test_main(): diff --git a/uv.lock b/uv.lock index 2f5cd64..328fe2c 100644 --- a/uv.lock +++ b/uv.lock @@ -193,6 +193,41 @@ toml = [ { name = "tomli", marker = "python_full_version >= '3.9' and python_full_version <= '3.11'" }, ] +[[package]] +name = "d2-python" +version = "1.1.0" +source = { editable = "." } + +[package.optional-dependencies] +coverage = [ + { name = "coverage", version = "7.6.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "coverage", version = "7.9.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "pytest-cov", version = "5.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "pytest-cov", version = "6.2.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, +] +dev = [ + { name = "mypy", version = "1.14.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "mypy", version = "1.16.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "pre-commit", version = "3.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "pre-commit", version = "4.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "ruff" }, +] +test = [ + { name = "pytest", version = "8.3.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "pytest", version = "8.4.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, +] + +[package.metadata] +requires-dist = [ + { name = "coverage", marker = "extra == 'coverage'", specifier = ">=6.5.0" }, + { name = "mypy", marker = "extra == 'dev'", specifier = ">=0.982" }, + { name = "pre-commit", marker = "extra == 'dev'", specifier = ">=2.20.0" }, + { name = "pytest", marker = "extra == 'test'", specifier = ">=7.1.3" }, + { name = "pytest-cov", marker = "extra == 'coverage'", specifier = ">=4.0.0" }, + { name = "ruff", marker = "extra == 'dev'", specifier = ">=0.12.3" }, +] +provides-extras = ["dev", "test", "coverage"] + [[package]] name = "distlib" version = "0.3.9" @@ -495,41 +530,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/88/74/a88bf1b1efeae488a0c0b7bdf71429c313722d1fc0f377537fbe554e6180/pre_commit-4.2.0-py2.py3-none-any.whl", hash = "sha256:a009ca7205f1eb497d10b845e52c838a98b6cdd2102a6c8e4540e94ee75c58bd", size = 220707, upload-time = "2025-03-18T21:35:19.343Z" }, ] -[[package]] -name = "py-d2" -version = "1.1.0" -source = { editable = "." } - -[package.optional-dependencies] -coverage = [ - { name = "coverage", version = "7.6.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "coverage", version = "7.9.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, - { name = "pytest-cov", version = "5.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "pytest-cov", version = "6.2.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, -] -dev = [ - { name = "mypy", version = "1.14.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "mypy", version = "1.16.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, - { name = "pre-commit", version = "3.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "pre-commit", version = "4.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, - { name = "ruff" }, -] -test = [ - { name = "pytest", version = "8.3.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "pytest", version = "8.4.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, -] - -[package.metadata] -requires-dist = [ - { name = "coverage", marker = "extra == 'coverage'", specifier = ">=6.5.0" }, - { name = "mypy", marker = "extra == 'dev'", specifier = ">=0.982" }, - { name = "pre-commit", marker = "extra == 'dev'", specifier = ">=2.20.0" }, - { name = "pytest", marker = "extra == 'test'", specifier = ">=7.1.3" }, - { name = "pytest-cov", marker = "extra == 'coverage'", specifier = ">=4.0.0" }, - { name = "ruff", marker = "extra == 'dev'", specifier = ">=0.12.3" }, -] -provides-extras = ["dev", "test", "coverage"] - [[package]] name = "pygments" version = "2.19.2" From 60c9113b633e15a2713c38d5855384194d45adba Mon Sep 17 00:00:00 2001 From: Robby Date: Fri, 11 Jul 2025 14:19:53 -0400 Subject: [PATCH 2/2] update version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index f81ec74..f59df9e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "d2-python" -version = "1.1.0" +version = "1.0.0" description = "An unofficial, fully typed python interface for building .d2 graph files in python." authors = [ {name = "David Revay", email = "daverevay@gmail.com"},