Repository navigation
v1.1.1: Examples That Actually Run
No behaviour changes. This release exists because the library's front door was broken: the example on the PyPI landing page had never run, seven of the fifteen tutorial notebooks raised on execution, two-thirds of the package had no API reference at all, and the annotations shipped invisible to downstream type checkers. Thanks to @the-moog for reporting #25, which started this.
Every documentation figure below was measured against a sphinx-build, and every example was verified by installing the built wheel into a clean virtualenv and running it.
Fixed
-
The examples on the PyPI landing page. Both README visualization snippets called
plot_kinematic_linkage(linkage), but that function takes(linkage, fig, axis, loci)and always has — the signature is identical in 1.0.0, so these examples never ran, on any release. They now callshow_linkage(), which builds the figure and runs the simulation itself. The PSO snippet separately usedget_num_constraints()/set_num_constraints(), removed earlier in the 1.x line; it now usesget_constraints()/set_constraints(). -
The front-page example did not say what to install. The first snippet in the README calls
path_generation()andshow_linkage(), which live behind thescipyandvizextras. Every other example needing an extra said so; this one did not, so after a plainpip install pylinkageit raisedModuleNotFoundErrorbefore reaching any pylinkage code. It now names the install line it needs. -
Type information was not exposed to users. The package is fully annotated and passes
mypy --stricton all 133 source files, but shipped no PEP 561py.typedmarker, so type checkers and editors in downstream projects silently ignored every annotation and treatedpylinkageas untyped. The marker is now in the wheel. -
Tutorial notebooks failing to execute. Seven of the fifteen raised against removed API:
get_num_constraints()/set_num_constraints()(notebooks 02, 03, 09, 10, 11, 13),SymbolicLinkage.componentsin place of.joints(05), andmechanism_to_linkage()(10). Notebook 10 additionally described the component/dyadLinkageas a "legacy" API throughout; the legacy API waspylinkage.joints, which no longer exists. ANotebooksCI workflow now executes every notebook on push and pull request, so this cannot silently return. -
Stale API reference.
docs/source/api/was checked-insphinx-apidocoutput not regenerated since before 1.0. It documented three modules that no longer exist — the legacypylinkage.jointspackage,pylinkage.collections, andpylinkage.linkage.linkage— which failed to import on every docs build. More importantly it covered only 6 of the package's 18 subpackages:synthesis,mechanism,hypergraph,cam,symbolic,solver,components,actuators,dyads,simulation,assur,bridge,populationandtopologyhad no API reference at all. -
Docstrings rendered wrongly in the API reference. The codebase writes Google-style docstrings, but the docs never enabled
sphinx.ext.napoleon, so every one was parsed as a definition list: parameter descriptions were swallowed as stray indentation, and*args/**kwargswere read as emphasis markup. Napoleon is now enabled, withnapoleon_use_ivarso a documented attribute does not collide with the entry autodoc already generates for the same dataclass field, and:no-index:on package-levelautomoduledirectives so each object is indexed once rather than once per re-export. Nine genuinely malformed docstrings were fixed by hand. -
Documentation links that pointed at the wrong class.
pylinkage.dyadsexportsDyadas a plain alias ofComponent, and the package annotated its anchors with that alias. Two unrelated classes are also namedDyad(pylinkage.assur.Dyad, an Assur group, andpylinkage.synthesis.Dyad, a Burmester construct), so Sphinx resolved those annotations to one of them and sent readers to a class the code never referred to. The annotations now nameComponentdirectly; the aliases remain exported and unchanged, so no import breaks. -
Broken README links, on three surfaces at once. The links to the 15 tutorial notebooks,
CONTRIBUTING.mdandCODE_OF_CONDUCT.mdwere repository-relative, so they resolved only on GitHub and were dead on PyPI and in the rendered documentation. They are now absolute URLs. The README was also rendered twice in the docs — listed in the toctree and pulled in again with.. include::.
Together these take the documentation build from 496 warnings to 8, the remaining 8 being the genuine assur.Dyad / synthesis.Dyad name collision, which is deferred to 1.2.0 under the deprecation policy in #22.
Added
-
Public benchmarks, at
docs/source/benchmarks.md: figures for the numba solver, PSO throughput, and the three synthesis entry points, with the hardware they came from and the command that reproduces them. The harness measures the public API only, takes the median of repeated runs, and discards warmup so numba's one-off JIT compilation is not charged to steady-state figures. Headline numbers:step_fast()is 6.4xstep(), PSO sustains ~16,000 fitness evaluations per second on a four-bar, andpath_generation()costs well over a second because it searches 36 coupler orientations — worth knowing before calling it in a loop. -
pylinkage.dyads.to_mechanism()is now public. It converts a componentLinkageinto aMechanism, and previously existed only aspylinkage.dyads._conversion.to_mechanism, so it could not be used or documented without reaching into a private module. The conversion remains one-way.
Changed
-
One docstring style across the codebase. Docstrings were split between two conventions: 85 files used Google style while 16 used reST field lists, and
linkage/transmission.pyused both at once. The 16 — concentrated insymbolic/,optimization/andgeometry/, the oldest code in the package — are converted to Google style. This is presentation only: 393 fields were rewritten with no change to wording. -
The
fullextra now includespymoo, sopip install pylinkage[full]covers multi-objective optimization as the README's "all optional backends" description promises.mooremains available on its own, and is now listed in the README's extras table.
Full changelog: v1.1.0...v1.1.1