]> Untitled Git - axy/ft/python02.git/commitdiff
Add solution for exercises 0 to 5
authorAxy <gilliardmarthey.axel@gmail.com>
Mon, 19 Jan 2026 14:51:08 +0000 (15:51 +0100)
committerAxy <gilliardmarthey.axel@gmail.com>
Mon, 19 Jan 2026 14:51:08 +0000 (15:51 +0100)
.gitignore [new file with mode: 0644]
ex0/ft_first_exception.py [new file with mode: 0644]
ex1/ft_different_errors.py [new file with mode: 0644]
ex2/ft_custom_errors.py [new file with mode: 0644]
ex3/ft_finally_block.py [new file with mode: 0644]
ex4/ft_raise_errors.py [new file with mode: 0644]
ex5/ft_garden_management.py [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..7a6cd49
--- /dev/null
@@ -0,0 +1,4 @@
+__pycache__/
+*.pdf
+*.txt
+.gemini/
diff --git a/ex0/ft_first_exception.py b/ex0/ft_first_exception.py
new file mode 100644 (file)
index 0000000..61787ca
--- /dev/null
@@ -0,0 +1,39 @@
+def check_temperature(temp_str: str) -> int | None:
+    """
+    Checks if the temperature is valid for plants (0-40).
+    Returns the temperature if valid, None otherwise.
+    """
+    try:
+        temp = int(temp_str)
+        if temp < 0:
+            print(f"Error: {temp}°C is too cold for plants (min 0°C)")
+            return None
+        elif temp > 40:
+            print(f"Error: {temp}°C is too hot for plants (max 40°C)")
+            return None
+        else:
+            return temp
+    except ValueError:
+        print(f"Error: '{temp_str}' is not a valid number")
+        return None
+
+
+def test_temperature_input() -> None:
+    """
+    Demonstrates testing with various inputs.
+    """
+    print("=== Garden Temperature Checker ===")
+
+    inputs = ["25", "abc", "100", "-50"]
+
+    for inp in inputs:
+        print(f"Testing temperature: {inp}")
+        result = check_temperature(inp)
+        if result is not None:
+            print(f"Temperature {result}°C is perfect for plants!")
+
+    print("All tests completed - program didn't crash!")
+
+
+if __name__ == "__main__":
+    test_temperature_input()
diff --git a/ex1/ft_different_errors.py b/ex1/ft_different_errors.py
new file mode 100644 (file)
index 0000000..a6f88b1
--- /dev/null
@@ -0,0 +1,53 @@
+def garden_operations() -> None:
+    """
+    Demonstrates handling of different exception types in garden operations.
+    """
+    print("=== Garden Error Types Demo ===")
+
+    # ValueError
+    print("Testing ValueError...")
+    try:
+        int("abc")
+    except ValueError as e:
+        print(f"Caught ValueError: {e}")
+
+    # ZeroDivisionError
+    print("Testing ZeroDivisionError...")
+    try:
+        10 / 0
+    except ZeroDivisionError as e:
+        print(f"Caught ZeroDivisionError: {e}")
+
+    # FileNotFoundError
+    print("Testing FileNotFoundError...")
+    try:
+        open("missing.txt", "r")
+    except FileNotFoundError:
+        print("Caught FileNotFoundError: No such file 'missing.txt'")
+
+    # KeyError
+    print("Testing KeyError...")
+    try:
+        d = {}
+        _ = d["missing_plant"]
+    except KeyError as e:
+        print(f"Caught KeyError: {e}")
+
+    # Multiple errors
+    print("Testing multiple errors together...")
+    try:
+        int("abc")
+    except (ValueError, ZeroDivisionError):
+        print("Caught an error, but program continues!")
+
+
+def test_error_types() -> None:
+    """
+    Runs the garden operations demonstration.
+    """
+    garden_operations()
+    print("All error types tested successfully!")
+
+
+if __name__ == "__main__":
+    test_error_types()
diff --git a/ex2/ft_custom_errors.py b/ex2/ft_custom_errors.py
new file mode 100644 (file)
index 0000000..1917cd5
--- /dev/null
@@ -0,0 +1,52 @@
+class GardenError(Exception):
+    """Base class for garden-related errors."""
+
+    pass
+
+
+class PlantError(GardenError):
+    """Error related to plants."""
+
+    pass
+
+
+class WaterError(GardenError):
+    """Error related to watering."""
+
+    pass
+
+
+def test_custom_errors() -> None:
+    """
+    Demonstrates raising and catching custom exceptions.
+    """
+    print("=== Custom Garden Errors Demo ===")
+
+    print("Testing PlantError...")
+    try:
+        raise PlantError("The tomato plant is wilting!")
+    except PlantError as e:
+        print(f"Caught PlantError: {e}")
+
+    print("Testing WaterError...")
+    try:
+        raise WaterError("Not enough water in the tank!")
+    except WaterError as e:
+        print(f"Caught WaterError: {e}")
+
+    print("Testing catching all garden errors...")
+    try:
+        raise PlantError("The tomato plant is wilting!")
+    except GardenError as e:
+        print(f"Caught a garden error: {e}")
+
+    try:
+        raise WaterError("Not enough water in the tank!")
+    except GardenError as e:
+        print(f"Caught a garden error: {e}")
+
+    print("All custom error types work correctly!")
+
+
+if __name__ == "__main__":
+    test_custom_errors()
diff --git a/ex3/ft_finally_block.py b/ex3/ft_finally_block.py
new file mode 100644 (file)
index 0000000..de5d73b
--- /dev/null
@@ -0,0 +1,33 @@
+def water_plants(plant_list: list) -> None:
+    """
+    Waters plants in the list, ensuring cleanup happens.
+    """
+    try:
+        print("Opening watering system")
+        for plant in plant_list:
+            if not isinstance(plant, str):
+                raise TypeError(f"Cannot water {plant} - invalid plant!")
+            print(f"Watering {plant}")
+    except TypeError as e:
+        print(f"Error: {e}")
+    finally:
+        print("Closing watering system (cleanup)")
+
+
+def test_watering_system() -> None:
+    """
+    Tests the watering system with valid and invalid lists.
+    """
+    print("=== Garden Watering System ===")
+
+    print("Testing normal watering...")
+    water_plants(["tomato", "lettuce", "carrots"])
+    print("Watering completed successfully!")
+
+    print("Testing with error...")
+    water_plants(["tomato", None, "carrots"])
+    print("Cleanup always happens, even with errors!")
+
+
+if __name__ == "__main__":
+    test_watering_system()
diff --git a/ex4/ft_raise_errors.py b/ex4/ft_raise_errors.py
new file mode 100644 (file)
index 0000000..f9e66ba
--- /dev/null
@@ -0,0 +1,64 @@
+def check_plant_health(
+    plant_name: str, water_level: int, sunlight_hours: int
+) -> str:
+    """
+    Checks if plant parameters are within valid ranges.
+    Raises ValueError if not.
+    """
+    if not plant_name:
+        raise ValueError("Plant name cannot be empty!")
+
+    if water_level < 1 or water_level > 10:
+        if water_level > 10:
+            raise ValueError(f"Water level {water_level} is too high (max 10)")
+        else:
+            raise ValueError(f"Water level {water_level} is too low (min 1)")
+
+    if sunlight_hours < 2 or sunlight_hours > 12:
+        if sunlight_hours < 2:
+            raise ValueError(
+                f"Sunlight hours {sunlight_hours} is too low (min 2)"
+            )
+        else:
+            raise ValueError(
+                f"Sunlight hours {sunlight_hours} is too high (max 12)"
+            )
+
+    return f"Plant '{plant_name}' is healthy!"
+
+
+def test_plant_checks() -> None:
+    """
+    Tests plant health check with various invalid inputs.
+    """
+    print("=== Garden Plant Health Checker ===")
+
+    print("Testing good values...")
+    try:
+        print(check_plant_health("tomato", 5, 8))
+    except ValueError as e:
+        print(f"Error: {e}")
+
+    print("Testing empty plant name...")
+    try:
+        check_plant_health("", 5, 8)
+    except ValueError as e:
+        print(f"Error: {e}")
+
+    print("Testing bad water level...")
+    try:
+        check_plant_health("lettuce", 15, 8)
+    except ValueError as e:
+        print(f"Error: {e}")
+
+    print("Testing bad sunlight hours...")
+    try:
+        check_plant_health("carrot", 5, 0)
+    except ValueError as e:
+        print(f"Error: {e}")
+
+    print("All error raising tests completed!")
+
+
+if __name__ == "__main__":
+    test_plant_checks()
diff --git a/ex5/ft_garden_management.py b/ex5/ft_garden_management.py
new file mode 100644 (file)
index 0000000..731e95d
--- /dev/null
@@ -0,0 +1,115 @@
+class GardenError(Exception):
+    """Base class for garden-related errors."""
+
+    pass
+
+
+class PlantError(GardenError):
+    """Error related to plants."""
+
+    pass
+
+
+class WaterError(GardenError):
+    """Error related to watering."""
+
+    pass
+
+
+class GardenManager:
+    """
+    Manages a garden with resilient error handling.
+    """
+
+    def __init__(self):
+        self.plants = []
+
+    def add_plant(self, name: str) -> None:
+        """
+        Adds a plant to the garden.
+        Raises PlantError if name is invalid.
+        """
+        if not name:
+            raise PlantError("Plant name cannot be empty!")
+        self.plants.append(name)
+        print(f"Added {name} successfully")
+
+    def water_plants(self) -> None:
+        """
+        Waters all plants in the garden.
+        Uses finally block for cleanup.
+        """
+        print("Opening watering system")
+        try:
+            for plant in self.plants:
+                print(f"Watering {plant} - success")
+        except Exception as e:
+            print(f"Error watering: {e}")
+        finally:
+            print("Closing watering system (cleanup)")
+
+    def check_plant_health(
+        self, name: str, water_level: int, sun_hours: int
+    ) -> None:
+        """
+        Checks health of a plant.
+        Raises GardenError (or subclasses) if conditions are bad.
+        """
+        try:
+            if name not in self.plants:
+                raise PlantError(f"Plant {name} not in garden")
+
+            if water_level < 0 or water_level > 10:
+                if water_level > 10:
+                    raise WaterError(
+                        f"Water level {water_level} is too high (max 10)"
+                    )
+                else:
+                    raise WaterError(
+                        f"Water level {water_level} is too low (min 0)"
+                    )
+
+            if sun_hours < 0:
+                raise GardenError("Sunlight cannot be negative")
+
+            print(f"{name}: healthy (water: {water_level}, sun: {sun_hours})")
+
+        except GardenError as e:
+            print(f"Error checking {name}: {e}")
+
+
+def test_garden_management() -> None:
+    """
+    Demonstrates the full garden management system.
+    """
+    print("=== Garden Management System ===")
+    manager = GardenManager()
+
+    print("Adding plants to garden...")
+    try:
+        manager.add_plant("tomato")
+        manager.add_plant("lettuce")
+        manager.add_plant("")
+    except PlantError as e:
+        print(f"Error adding plant: {e}")
+
+    print("Watering plants...")
+    manager.water_plants()
+
+    print("Checking plant health...")
+    manager.check_plant_health("tomato", 5, 8)
+    manager.check_plant_health("lettuce", 15, 8)
+
+    print("Testing error recovery...")
+    try:
+        # Simulate a critical error condition we want to catch explicitly
+        raise GardenError("Not enough water in tank")
+    except GardenError as e:
+        print(f"Caught GardenError: {e}")
+        print("System recovered and continuing...")
+
+    print("Garden management system test complete!")
+
+
+if __name__ == "__main__":
+    test_garden_management()