Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ Attention: The newest changes should be on top -->

### Added

- ENH: Custom Exception errors and messages [#285](https://github.com/RocketPy-Team/RocketPy/issues/285)

### Changed

### Fixed
Expand Down
26 changes: 26 additions & 0 deletions rocketpy/rocket/rocket.py
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,32 @@ def __init__( # pylint: disable=too-many-statements
self.prints = _RocketPrints(self)
self.plots = _RocketPlots(self)

def _check_missing_components(self):
"""Check if the rocket is missing any essential components and issue a warning.

This method verifies whether the rocket has the following key components:
- motor
- aerodynamic surface(s)

If any of these components are missing, a single warning message is issued
listing all missing components. This helps users quickly identify potential
issues before running simulations or analyses.

Notes:
- The warning uses Python's built-in `warnings.warn` function.
"""
missing_components = []
if isinstance(self.motor, EmptyMotor):
missing_components.append("motor")
if not self.aerodynamic_surfaces or len(self.aerodynamic_surfaces) == 0:
missing_components.append("aerodynamic surfaces")

if missing_components:
component_list = ", ".join(missing_components)
warnings.warn(
f"[WARNING] Rocket has no {component_list} defined.", UserWarning
)

@property
def nosecones(self):
"""A list containing all the nose cones currently added to the rocket."""
Expand Down
37 changes: 36 additions & 1 deletion tests/unit/rocket/test_rocket.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@


@patch("matplotlib.pyplot.show")
def test_elliptical_fins(mock_show, calisto_robust, calisto_trapezoidal_fins): # pylint: disable=unused-argument
def test_elliptical_fins(
mock_show, calisto_robust, calisto_trapezoidal_fins
): # pylint: disable=unused-argument
test_rocket = calisto_robust
calisto_robust.aerodynamic_surfaces.remove(calisto_trapezoidal_fins)
test_rocket.add_elliptical_fins(4, span=0.100, root_chord=0.120, position=-1.168)
Expand Down Expand Up @@ -370,6 +372,39 @@ def test_add_motor(calisto_motorless, cesaroni_m1670):
assert center_of_mass_motorless is not center_of_mass_with_motor


def test_check_missing_all_components(calisto_motorless):
"""Tests the _check_missing_components method for a Rocket with no components."""
with pytest.warns(UserWarning) as record:
calisto_motorless._check_missing_components()

assert len(record) == 1
msg = str(record[0].message)
assert "motor" in msg
assert "aerodynamic surfaces" in msg


def test_check_missing_some_components(calisto):
"""Tests the _check_missing_components method for a Rocket missing some components."""
calisto.parachutes = []
calisto.aerodynamic_surfaces = []

with pytest.warns(UserWarning) as record:
calisto._check_missing_components()

assert len(record) == 1
msg = str(record[0].message)
assert "aerodynamic surfaces" in msg


def test_check_missing_no_components_missing(calisto_robust):
"""Tests the _check_missing_components method for a complete Rocket."""
# Call directly — no warnings expected
with pytest.warns(None) as record:
calisto_robust._check_missing_components()
# If any warning occurs, pytest will fail automatically
assert len(record) == 0


def test_set_rail_button(calisto):
rail_buttons = calisto.set_rail_buttons(0.2, -0.5, 30)
# assert buttons_distance
Expand Down
Loading