Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support invisible nodes and fix arrows #1

Open
wants to merge 5 commits into
base: base-sha/0c0cf618533f05e19a2ea0ba81b4e8842864ea00
Choose a base branch
from

Conversation

sourcery-ai-experiments-bot
Copy link
Collaborator

@sourcery-ai-experiments-bot sourcery-ai-experiments-bot commented Jul 8, 2024

Addresses hbmartin#67

Summary by Sourcery

This pull request introduces support for invisible nodes in edge handling and fixes issues with arrow rendering. It includes refactoring of edge style generation and updates to the README and test cases.

  • New Features:
    • Added support for invisible nodes in edge handling.
  • Bug Fixes:
    • Fixed issues with arrow rendering, including no arrows and double arrows.
  • Enhancements:
    • Refactored edge style generation to handle both start and end arrow styles.
    • Improved handling of edge source and target nodes, allowing for None values.
  • Documentation:
    • Updated README to reflect the completion of invisible node handling and arrow fixes.
  • Tests:
    • Added a new test case for invisible nodes to ensure correct XML generation.

Summary by CodeRabbit

  • New Features

    • Improved handling of Bezier curves and invisible nodes.
    • Added support for image and tooltip display.
    • Introduced EDGE_INVIS attribute for invisible edges.
  • Bug Fixes

    • Corrected issues with no arrows and double arrows.
  • Tests

    • Added test_invisible function to validate Graphviz to Draw.io XML conversion.
  • Documentation

    • Updated README with progress on roadmap tasks for upcoming versions.
  • Enhancements

    • Enhanced edge style handling and attribute management.
    • Improved parsing for nodes, edges, and clusters with additional parameters.
  • Refactor

    • Simplified methods in Rect.py for ratio calculations.
    • Added constants for edge directions in DotAttr.py.

@sourcery-ai-experiments-bot
Copy link
Collaborator Author

This is a benchmark review for experiment review_of_reviews_20240708.
Run ID: review_of_reviews_20240708/benchmark_2024-07-08T00-18-37_v1-20-0-4-gb56c705c9.

This pull request was cloned from https://github.com/hbmartin/graphviz2drawio/pull/83. (Note: the URL is not a link to avoid triggering a notification on the original pull request.)

Experiment configuration
review_config:
  # User configuration for the review
  # - benchmark - use the user config from the benchmark reviews
  # - <value> - use the value directly
  user_review_config:
    enable_ai_review: true
    enable_rule_comments: false

    enable_complexity_comments: benchmark
    enable_security_comments: benchmark
    enable_tests_comments: benchmark
    enable_comment_suggestions: benchmark
    enable_functionality_review: benchmark

    enable_pull_request_summary: benchmark
    enable_review_guide: benchmark

    enable_approvals: true

  ai_review_config:
    # The model responses to use for the experiment
    # - benchmark - use the model responses from the benchmark reviews
    # - llm - call the language model to generate responses
    model_responses:
      comments_model: benchmark
      comment_area_model: benchmark
      comment_validation_model: benchmark
      comment_suggestion_model: benchmark
      complexity_model: benchmark
      docstrings_model: benchmark
      functionality_model: benchmark
      security_model: benchmark
      tests_model: benchmark
      pull_request_summary_model: benchmark
      review_guide_model: benchmark

# The pull request dataset to run the experiment on
pull_request_dataset:
- https://github.com/mraniki/iamlistening/pull/334
- https://github.com/mraniki/cefi/pull/475
- https://github.com/mraniki/MyLLM/pull/581
- https://github.com/mraniki/dxsp/pull/689
- https://github.com/jschalk/jaar/pull/239
- https://github.com/jschalk/jaar/pull/241
- https://github.com/jschalk/jaar/pull/242
- https://github.com/iptux-src/iptux/pull/620
- https://github.com/iptux-src/iptux/pull/622
- https://github.com/hacksider/Deep-Live-Cam/pull/46
- https://github.com/mnbf9rca/super_simple_tfl_status/pull/114
- https://github.com/mnbf9rca/super_simple_tfl_status/pull/115
- https://github.com/RockProfile/Django-deployment/pull/1
- https://github.com/hbmartin/graphviz2drawio/pull/83
- https://github.com/fairdataihub/codefair-app/pull/28
- https://github.com/totaldebug/atomic-calendar-revive/pull/1518
- https://github.com/iammiracle01/portfolio/pull/1
- https://github.com/iammiracle01/portfolio/pull/2
- https://github.com/iammiracle01/portfolio/pull/3
- https://github.com/supermario-ai/gpt-crawler/pull/1
- https://github.com/hbmartin/graphviz2drawio/pull/84
- https://github.com/hbmartin/graphviz2drawio/pull/85
- https://github.com/dreamerminsk/tasked/pull/85
- https://github.com/dreamerminsk/tasked/pull/86
- https://github.com/dreamerminsk/tasked/pull/84
- https://github.com/haalasz/fm-tools/pull/9
- https://github.com/haalasz/fm-tools/pull/10
- https://github.com/iptux-src/iptux/pull/619
- https://github.com/code-Harsh247/medsymptom/pull/1
- https://github.com/code-Harsh247/medsymptom/pull/2
- https://github.com/cpp-lln-lab/bidspm/pull/1263
- https://github.com/cpp-lln-lab/bidspm/pull/1264
- https://github.com/cpp-lln-lab/bidspm/pull/1265
- https://github.com/luiscarlop/Judge_AI/pull/22
- https://github.com/NoNormalCreeper/nonebot_plugin_wolfram/pull/6
- https://github.com/osama1998H/kalima/pull/39
- https://github.com/osama1998H/kalima/pull/40
- https://github.com/osama1998H/kalima/pull/41
- https://github.com/jackdewinter/pymarkdown/pull/1131
- https://github.com/Eliver-Salazar/PED/pull/12
- https://github.com/NextAlone/Nagram/pull/40
- https://github.com/strawberry-graphql/strawberry-django/pull/575
- https://github.com/strawberry-graphql/strawberry/pull/3558
- https://github.com/strawberry-graphql/strawberry/pull/3559
- https://github.com/Ruin2121/yahooquery/pull/9
- https://github.com/gdsfactory/gdsfactory/pull/2951
- https://github.com/gdsfactory/gdsfactory/pull/2954
- https://github.com/gdsfactory/gdsfactory/pull/2956
- https://github.com/gdsfactory/gdsfactory/pull/2957
- https://github.com/gdsfactory/cspdk/pull/51
review_comment_labels:
- label: correct
  question: Is this comment correct?
- label: helpful
  question: Is this comment helpful?
- label: comment-type
  question: Is the comment type correct?
- label: comment-area
  question: Is the comment area correct?
- label: llm-test
  question: |
    What type of LLM test could this comment become?
    - 👍 - this comment is really good/important and we should always make it
    - 👎 - this comment is really bad and we should never make it
    - no reaction - don't turn this comment into an LLM test

# Benchmark reviews generated by running
#   python -m scripts.experiment benchmark <experiment_name>
benchmark_reviews: []

@SourceryAI
Copy link

SourceryAI commented Jul 8, 2024

Reviewer's Guide by Sourcery

This pull request introduces support for invisible nodes in edges and fixes issues related to arrow rendering. It also includes enhancements to edge style handling, updates the README to reflect these changes, and adds a new test case to verify the correct handling of invisible nodes.

File-Level Changes

Files Changes
graphviz2drawio/mx/MxGraph.py
graphviz2drawio/mx/Edge.py
Refactored edge handling to support invisible nodes and improved arrow rendering.
graphviz2drawio/models/Rect.py
graphviz2drawio/mx/EdgeFactory.py
Simplified ratio calculations and added support for directed edges in EdgeFactory.
graphviz2drawio/graphviz2drawio.py
graphviz2drawio/models/SvgParser.py
Updated parsing logic to handle directed graphs.
graphviz2drawio/mx/Styles.py
graphviz2drawio/models/DotAttr.py
Enhanced edge styles and added new constants for edge directions.

Tips
  • Trigger a new Sourcery review by commenting @sourcery-ai review on the pull request.
  • Continue your discussion with Sourcery by replying directly to review comments.
  • You can change your review settings at any time by accessing your dashboard:
    • Enable or disable the Sourcery-generated pull request summary or reviewer's guide;
    • Change the review language;
  • You can always contact us if you have any questions or feedback.

Copy link

@SourceryAI SourceryAI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @sourcery-ai-experiments-bot - I've reviewed your changes and they look great!

Here's what I looked at during the review
  • 🟡 General issues: 2 issues found
  • 🟢 Security: all looks good
  • 🟡 Testing: 3 issues found
  • 🟡 Complexity: 3 issues found
  • 🟢 Documentation: all looks good

LangSmith trace

Help me be more useful! Please click 👍 or 👎 on each comment to tell me if it was helpful.

Comment on lines +68 to +70
def get_edge_source_target(self, edge: Edge) -> tuple[Node | None, Node | None]:
if edge.dir == DotAttr.BACK:
return self.nodes[edge.to], self.nodes[edge.fr]
return self.nodes[edge.fr], self.nodes[edge.to]

@staticmethod
def get_edge_style(
edge: Edge, # pytype: disable=invalid-annotation
source_geo: Rect | None,
target_geo: Rect | None,
) -> str:
end_arrow = MxConst.BLOCK
end_fill = 1
dashed = 1 if edge.line_style == DotAttr.DASHED else 0
if edge.arrowtail is not None:
tail = edge.arrowtail
if edge.arrowtail[0] == DotAttr.NO_FILL:
end_fill = 0
tail = edge.arrowtail[1:]
if tail == DotAttr.DIAMOND:
end_arrow = MxConst.DIAMOND
if edge.curve is not None:
style = Styles.EDGE.format(
end_arrow=end_arrow,
dashed=dashed,
end_fill=end_fill,
) + (MxConst.CURVED if edge.curve.is_bezier else MxConst.SHARP)

if source_geo is not None:
exit_x, exit_y = source_geo.relative_location_along_perimeter(
edge.curve.start,
)
style += f"exitX={exit_x};exitY={exit_y};"
if target_geo is not None:
entry_x, entry_y = target_geo.relative_location_along_perimeter(
edge.curve.end,
)
style += f"entryX={entry_x};entryY={entry_y};"

return style

return Styles.EDGE.format(
end_arrow=end_arrow,
dashed=dashed,
end_fill=end_fill,
)
return self.nodes.get(edge.to), self.nodes.get(edge.fr)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Consider using Optional for type hinting.

Using Optional[Node] instead of Node | None can improve readability and consistency with common Python type hinting practices.

Suggested change
def get_edge_source_target(self, edge: Edge) -> tuple[Node | None, Node | None]:
if edge.dir == DotAttr.BACK:
return self.nodes[edge.to], self.nodes[edge.fr]
return self.nodes[edge.fr], self.nodes[edge.to]
@staticmethod
def get_edge_style(
edge: Edge, # pytype: disable=invalid-annotation
source_geo: Rect | None,
target_geo: Rect | None,
) -> str:
end_arrow = MxConst.BLOCK
end_fill = 1
dashed = 1 if edge.line_style == DotAttr.DASHED else 0
if edge.arrowtail is not None:
tail = edge.arrowtail
if edge.arrowtail[0] == DotAttr.NO_FILL:
end_fill = 0
tail = edge.arrowtail[1:]
if tail == DotAttr.DIAMOND:
end_arrow = MxConst.DIAMOND
if edge.curve is not None:
style = Styles.EDGE.format(
end_arrow=end_arrow,
dashed=dashed,
end_fill=end_fill,
) + (MxConst.CURVED if edge.curve.is_bezier else MxConst.SHARP)
if source_geo is not None:
exit_x, exit_y = source_geo.relative_location_along_perimeter(
edge.curve.start,
)
style += f"exitX={exit_x};exitY={exit_y};"
if target_geo is not None:
entry_x, entry_y = target_geo.relative_location_along_perimeter(
edge.curve.end,
)
style += f"entryX={entry_x};entryY={entry_y};"
return style
return Styles.EDGE.format(
end_arrow=end_arrow,
dashed=dashed,
end_fill=end_fill,
)
return self.nodes.get(edge.to), self.nodes.get(edge.fr)
def get_edge_source_target(self, edge: Edge) -> tuple[Optional[Node], Optional[Node]]:
if edge.dir == DotAttr.BACK:
return self.nodes.get(edge.to), self.nodes.get(edge.fr)
return self.nodes.get(edge.fr), self.nodes.get(edge.to)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this comment correct?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this comment helpful?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the comment type correct?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the comment area correct?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What type of LLM test could this comment become?

  • 👍 - this comment is really good/important and we should always make it
  • 👎 - this comment is really bad and we should never make it
  • no reaction - don't turn this comment into an LLM test

@@ -1,10 +1,18 @@
_whitelist_attrs = ["dir"]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Consider renaming _whitelist_attrs to _allowed_attrs.

The term 'whitelist' can be replaced with 'allowed' to use more inclusive language. Consider renaming _whitelist_attrs to _allowed_attrs.

Suggested change
_whitelist_attrs = ["dir"]
_allowed_attrs = ["dir"]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this comment correct?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this comment helpful?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the comment type correct?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the comment area correct?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What type of LLM test could this comment become?

  • 👍 - this comment is really good/important and we should always make it
  • 👎 - this comment is really bad and we should never make it
  • no reaction - don't turn this comment into an LLM test

@@ -173,6 +173,15 @@ def test_subgraph_and_colors():
assert "clust2" in xml


def test_invisible():

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (testing): Consider adding more assertions to test edge cases.

The test_invisible function currently checks for a specific string in the XML. It would be beneficial to add more assertions to cover additional edge cases, such as verifying the absence of visible nodes and ensuring that other attributes are correctly set.

Suggested change
def test_invisible():
def test_invisible():
file = "test/directed/invisible.gv.txt"
xml = graphviz2drawio.convert(file)
assert "clust2" in xml
assert "visible" not in xml
assert "<node" not in xml
assert "<edge" not in xml

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this comment correct?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this comment helpful?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the comment type correct?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the comment area correct?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What type of LLM test could this comment become?

  • 👍 - this comment is really good/important and we should always make it
  • 👎 - this comment is really bad and we should never make it
  • no reaction - don't turn this comment into an LLM test


root = ElementTree.fromstring(xml)
check_xml_top(root)
assert ';exitX=1.0000;exitY=0.5839;"' in xml

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (testing): Use more descriptive assertion messages.

Adding descriptive messages to assertions can help quickly identify the cause of a test failure. For example: assert ';exitX=1.0000;exitY=0.5839;"' in xml, 'Invisible node exit coordinates not found in XML'.

Suggested change
assert ';exitX=1.0000;exitY=0.5839;"' in xml
assert ';exitX=1.0000;exitY=0.5839;"' in xml, 'Invisible node exit coordinates not found in XML'

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this comment correct?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this comment helpful?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the comment type correct?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the comment area correct?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What type of LLM test could this comment become?

  • 👍 - this comment is really good/important and we should always make it
  • 👎 - this comment is really bad and we should never make it
  • no reaction - don't turn this comment into an LLM test

file = "test/directed/invisible.gv.txt"
xml = graphviz2drawio.convert(file)

root = ElementTree.fromstring(xml)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (testing): Check for the correct handling of invisible edges.

Consider adding assertions to verify that invisible edges are handled correctly. This could include checking that the edges are present in the XML but not rendered, and that their attributes are set as expected.

Suggested change
root = ElementTree.fromstring(xml)
root = ElementTree.fromstring(xml)
invisible_edges = root.findall(".//edge[@style='invis']")
assert len(invisible_edges) > 0
for edge in invisible_edges:
assert edge.get('rendered') == 'false'

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this comment correct?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this comment helpful?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the comment type correct?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the comment area correct?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What type of LLM test could this comment become?

  • 👍 - this comment is really good/important and we should always make it
  • 👎 - this comment is really bad and we should never make it
  • no reaction - don't turn this comment into an LLM test

if search < self.x:
return 0
if search > self.x + self.width:
return 1
ratio = (search - self.x) / self.width
return self._approx(ratio, 0.5, 0.1)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (complexity): Consider keeping the _approx method and adding type annotations for clarity.

The new code is more complex and loses some of the original functionality. Specifically:

  1. The _approx method, which provided a way to approximate the ratio to a center value within a delta, has been removed. This might lead to less precise results in x_ratio and y_ratio methods.
  2. While type annotations are a good practice, they add a layer of complexity if the team is not familiar with them. However, this is a minor point compared to the loss of functionality.
  3. The original code had a clear separation of concerns with the _approx method, making it easier to understand and maintain. The new code inlines the ratio calculation, which can make it harder to modify or extend in the future.

To address these issues, consider keeping the _approx method and adding type annotations for clarity:

class Rectangle:
    def __init__(self, x: float, y: float, width: float, height: float, image: str) -> None:
        # x,y is the top left corner
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.bottom = y + height
        self.right = x + width
        self.image = image

    def x_ratio(self, search: float) -> float:
        if search < self.x:
            return 0
        if search > self.x + self.width:
            return 1
        ratio = (search - self.x) / self.width
        return self._approx(ratio, 0.5, 0.1)

    def y_ratio(self, search: float) -> float:
        if search < self.y:
            return 0
        if search > self.y + self.height:
            return 1
        ratio = (search - self.y) / self.height
        return self._approx(ratio, 0.5, 0.1)

    @staticmethod
    def _approx(value: float, center: float, delta: float) -> float:
        if abs(value - center) < delta:
            return center
        return value

    def to_dict_str(self) -> dict[str, str]:
        return {
            "x": str(self.x),
            "y": str(self.y),
            "width": str(self.width),
            "height": str(self.height),
        }

    def closest_point_along_perimeter(self, x: float, y: float) -> tuple[float, float]:
        x = clamp(x, self.x, self.right)
        y = clamp(y, self.y, self.bottom)
        return x, y

This approach maintains the original functionality and readability while adding type annotations for clarity.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this comment correct?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this comment helpful?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the comment type correct?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the comment area correct?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What type of LLM test could this comment become?

  • 👍 - this comment is really good/important and we should always make it
  • 👎 - this comment is really bad and we should never make it
  • no reaction - don't turn this comment into an LLM test

self.labels = labels

def get_edge_style(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (complexity): Consider simplifying the code by reducing methods and parameters.

The new code introduces additional complexity that could be simplified. Here are some points to consider:

  1. Increased Number of Methods: The new methods (get_edge_style and _get_arrow_shape_and_fill) add complexity without significantly improving modularity. They are tightly coupled with the internal state of the Edge class.

  2. Additional Parameters: The get_edge_style method introduces source_geo and target_geo parameters, increasing cognitive load.

  3. Conditional Logic: The new methods contain multiple layers of conditional logic, making the code harder to follow and maintain.

  4. Duplication of Logic: There is some duplication in how styles are formatted and how arrow shapes and fills are determined, which could lead to maintenance issues.

  5. Increased Dependencies: The new code introduces dependencies on additional modules (Rect, MxConst, and Styles), increasing complexity and making it harder to test in isolation.

Consider simplifying the code by removing unnecessary parameters, reducing nested conditionals, and consolidating style formatting logic. This will make the code easier to read, understand, and maintain.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this comment correct?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this comment helpful?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the comment type correct?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the comment area correct?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What type of LLM test could this comment become?

  • 👍 - this comment is really good/important and we should always make it
  • 👎 - this comment is really bad and we should never make it
  • no reaction - don't turn this comment into an LLM test

EDGE_LABEL = (
"edgeLabel;html=1;align=center;verticalAlign=bottom;resizable=0;points=[];"
)
EDGE_INVIS = "rounded=1;html=1;exitX={exit_x:.3g};exitY={exit_y:.3g};jettySize=auto;curved={curved};endArrow={end_arrow};dashed={dashed};endFill={end_fill};"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (complexity): Consider refactoring to reuse the existing EDGE style and only override the necessary properties.

The new code introduces a new style EDGE_INVIS which has a lot of overlap with the existing EDGE style, leading to increased duplication and maintenance complexity. Consider refactoring to reuse the existing EDGE style and only override the necessary properties. This will reduce duplication, improve maintainability, and ensure consistency. Here's a suggested refactor:

from enum import Enum
from . import Shape

class Styles(Enum):
    NODE = "verticalAlign=top;align=left;overflow=fill;html=1;rounded=0;shadow=0;comic=0;labelBackgroundColor=none;strokeColor={stroke};strokeWidth=1;fillColor={fill};"
    EDGE = "html=1;endArrow={end_arrow};dashed={dashed};endFill={end_fill};startArrow={start_arrow};startFill={start_fill};"
    EDGE_LABEL = "edgeLabel;html=1;align=center;verticalAlign=bottom;resizable=0;points=[];"
    TEXT = "margin:0px;text-align:{align};{margin};font-size:{size}px;font-family:{family};color:{color};"

    ELLIPSE = "ellipse;" + NODE
    CIRCLE = "ellipse;aspect=fixed;" + NODE
    HEXAGON = "shape=hexagon;perimeter=hexagonPerimeter2;" + NODE
    EGG = "shape=mxgraph.flowchart.display;direction=south;" + NODE
    TRIANGLE = "triangle;direction=north;" + NODE
    LINE = "line;strokeWidth=2;verticalAlign=bottom;labelPosition=center;verticalLabelPosition=top;align=center;" + NODE

    @staticmethod
    def edge_invis(exit_x, exit_y, curved, end_arrow, dashed, end_fill):
        return f"rounded=1;html=1;exitX={exit_x:.3g};exitY={exit_y:.3g};jettySize=auto;curved={curved};" + Styles.EDGE.format(
            end_arrow=end_arrow, dashed=dashed, end_fill=end_fill, start_arrow="", start_fill=""
        )

This approach keeps the code DRY (Don't Repeat Yourself) and makes it more modular and maintainable.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this comment correct?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this comment helpful?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the comment type correct?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the comment area correct?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What type of LLM test could this comment become?

  • 👍 - this comment is really good/important and we should always make it
  • 👎 - this comment is really bad and we should never make it
  • no reaction - don't turn this comment into an LLM test

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants