Skip to content

refactor(synthesis): publish crank_angle_limits - #47

Merged
HugoFara merged 1 commit into
mainfrom
refactor/public-crank-angle-limits
Sep 12, 2026
Merged

HugoFara merged 1 commit into
mainfrom
refactor/public-crank-angle-limits

Conversation

@HugoFara

Copy link
Copy Markdown
Owner

Summary

synthesis.conversion._compute_crank_limits becomes the public pylinkage.synthesis.crank_angle_limits(crank, coupler, rocker, ground).

Nothing in pylinkage called the private helper. Its only caller was the editor's backend in api/, reaching across the underscore. That backend is about to move into pylinkage-editor with pylinkage as a dependency (context in #46), and a dependency should have no private names to lean on.

What changes

  • The function moves to synthesis/utils.py beside grashof_check and is_crank_rocker, with their parameter names. Same logic; the docstring now states the angle convention (measured from the ground line, positive branch) and the 0.02 rad margin, with a doctest.
  • Exported from pylinkage.synthesis.
  • api/services/synthesis_service.py imports the public name. That was its last private pylinkage import.
  • The old test only asserted "None or a tuple". TestCrankAngleLimits now checks the bounds against the law-of-cosines angles at the collinear positions, that positions inside the range let the coupler-rocker dyad assemble, and the case where the margin swallows the range.
  • Changelog entry.

No deprecation shim: the name was private.

Verification

  • tests/synthesis/: 243 passed.
  • ruff, mypy clean.
  • api/ still imports under --extra api.

_compute_crank_limits lived in synthesis.conversion as a private helper,
yet nothing in pylinkage called it. Its only caller was the editor's
backend in api/, reaching across the underscore. That backend is about
to move into its own repository with pylinkage as a dependency, and a
dependency should have no private names to lean on.

The function is a four-bar classification helper: given the four link
lengths, it returns the angular range of a crank that cannot rotate
fully, or None when it can. That places it beside grashof_check and
is_crank_rocker in synthesis.utils, with their parameter names, exported
from pylinkage.synthesis as crank_angle_limits.

The old test only asserted "None or a tuple". The new one checks the
bounds against the law-of-cosines angles at the collinear positions,
checks that positions inside the range let the coupler-rocker dyad
assemble, and covers the case where the margin swallows the range.

No deprecation shim: the name was private.
@HugoFara
HugoFara merged commit b8a6b23 into main Sep 12, 2026
9 checks passed
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.

1 participant