mirror of
https://github.com/DavidGailleton/42-Piscine_Python.git
synced 2026-04-28 16:14:35 +02:00
fix(ex4): add wraps to every functions;
mypy compliance
This commit is contained in:
@@ -1,222 +0,0 @@
|
||||
"""
|
||||
FuncMage Chronicles - Data Generator Helper
|
||||
Generates test data for all exercises to help learners test their
|
||||
implementations
|
||||
"""
|
||||
|
||||
import random
|
||||
from typing import List, Dict, Any
|
||||
|
||||
|
||||
class FuncMageDataGenerator:
|
||||
"""Generate test data for FuncMage Chronicles exercises."""
|
||||
|
||||
# Fantasy-themed data pools
|
||||
MAGE_NAMES = [
|
||||
"Alex",
|
||||
"Jordan",
|
||||
"Riley",
|
||||
"Casey",
|
||||
"Morgan",
|
||||
"Sage",
|
||||
"River",
|
||||
"Phoenix",
|
||||
"Ember",
|
||||
"Storm",
|
||||
"Luna",
|
||||
"Nova",
|
||||
"Zara",
|
||||
"Kai",
|
||||
"Rowan",
|
||||
"Ash"]
|
||||
|
||||
ELEMENTS = [
|
||||
"fire",
|
||||
"ice",
|
||||
"lightning",
|
||||
"earth",
|
||||
"wind",
|
||||
"water",
|
||||
"light",
|
||||
"shadow"]
|
||||
|
||||
SPELL_NAMES = [
|
||||
"fireball", "heal", "shield", "lightning", "freeze", "earthquake",
|
||||
"tornado", "tsunami", "flash", "darkness", "meteor", "blizzard"
|
||||
]
|
||||
|
||||
ARTIFACT_NAMES = [
|
||||
"Crystal Orb",
|
||||
"Fire Staff",
|
||||
"Ice Wand",
|
||||
"Lightning Rod",
|
||||
"Earth Shield",
|
||||
"Wind Cloak",
|
||||
"Water Chalice",
|
||||
"Shadow Blade",
|
||||
"Light Prism",
|
||||
"Storm Crown"]
|
||||
|
||||
ARTIFACT_TYPES = ["weapon", "focus", "armor", "accessory", "relic"]
|
||||
|
||||
ENCHANTMENT_TYPES = [
|
||||
"Flaming",
|
||||
"Frozen",
|
||||
"Shocking",
|
||||
"Earthen",
|
||||
"Windy",
|
||||
"Flowing",
|
||||
"Radiant",
|
||||
"Dark"]
|
||||
|
||||
@classmethod
|
||||
def generate_mages(cls, count: int = 5) -> List[Dict[str, Any]]:
|
||||
"""Generate a list of mages with random attributes."""
|
||||
mages = []
|
||||
for _ in range(count):
|
||||
mage = {
|
||||
'name': random.choice(cls.MAGE_NAMES),
|
||||
'power': random.randint(50, 100),
|
||||
'element': random.choice(cls.ELEMENTS)
|
||||
}
|
||||
mages.append(mage)
|
||||
return mages
|
||||
|
||||
@classmethod
|
||||
def generate_artifacts(cls, count: int = 5) -> List[Dict[str, Any]]:
|
||||
"""Generate a list of magical artifacts."""
|
||||
artifacts = []
|
||||
for _ in range(count):
|
||||
artifact = {
|
||||
'name': random.choice(cls.ARTIFACT_NAMES),
|
||||
'power': random.randint(60, 120),
|
||||
'type': random.choice(cls.ARTIFACT_TYPES)
|
||||
}
|
||||
artifacts.append(artifact)
|
||||
return artifacts
|
||||
|
||||
@classmethod
|
||||
def generate_spells(cls, count: int = 6) -> List[str]:
|
||||
"""Generate a list of spell names."""
|
||||
return random.sample(cls.SPELL_NAMES, min(count, len(cls.SPELL_NAMES)))
|
||||
|
||||
@classmethod
|
||||
def generate_spell_powers(cls, count: int = 5) -> List[int]:
|
||||
"""Generate a list of spell power values."""
|
||||
return [random.randint(10, 50) for _ in range(count)]
|
||||
|
||||
@classmethod
|
||||
def generate_enchantment_items(cls, count: int = 5) -> List[str]:
|
||||
"""Generate a list of items to be enchanted."""
|
||||
items = [
|
||||
"Sword",
|
||||
"Shield",
|
||||
"Staff",
|
||||
"Wand",
|
||||
"Armor",
|
||||
"Ring",
|
||||
"Amulet",
|
||||
"Cloak"]
|
||||
return random.sample(items, min(count, len(items)))
|
||||
|
||||
@classmethod
|
||||
def print_exercise_data(cls, exercise_num: int):
|
||||
"""Print formatted test data for a specific exercise."""
|
||||
print(f"=== Exercise {exercise_num} Test Data ===")
|
||||
|
||||
if exercise_num == 0:
|
||||
print("# Lambda Sanctum Test Data")
|
||||
print("artifacts =", cls.generate_artifacts(4))
|
||||
print("mages =", cls.generate_mages(5))
|
||||
print("spells =", cls.generate_spells(4))
|
||||
|
||||
elif exercise_num == 1:
|
||||
print("# Higher Realm Test Data")
|
||||
print("# Use these in your test functions:")
|
||||
print("test_values =", [random.randint(5, 25) for _ in range(3)])
|
||||
print("test_targets =", ["Dragon", "Goblin", "Wizard", "Knight"])
|
||||
|
||||
elif exercise_num == 2:
|
||||
print("# Memory Depths Test Data")
|
||||
print(
|
||||
"initial_powers =", [
|
||||
random.randint(
|
||||
20, 80) for _ in range(3)])
|
||||
print(
|
||||
"power_additions =", [
|
||||
random.randint(
|
||||
5, 20) for _ in range(5)])
|
||||
print(
|
||||
"enchantment_types =",
|
||||
random.sample(
|
||||
cls.ENCHANTMENT_TYPES,
|
||||
3))
|
||||
print("items_to_enchant =", cls.generate_enchantment_items(4))
|
||||
|
||||
elif exercise_num == 3:
|
||||
print("# Ancient Library Test Data")
|
||||
print("spell_powers =", cls.generate_spell_powers(6))
|
||||
print("operations = ['add', 'multiply', 'max', 'min']")
|
||||
print(
|
||||
"fibonacci_tests =", [
|
||||
random.randint(
|
||||
8, 20) for _ in range(3)])
|
||||
|
||||
elif exercise_num == 4:
|
||||
print("# Master's Tower Test Data")
|
||||
print("test_powers =", [random.randint(5, 30) for _ in range(4)])
|
||||
print("spell_names =", random.sample(cls.SPELL_NAMES, 4))
|
||||
print("mage_names =", random.sample(cls.MAGE_NAMES, 6))
|
||||
print("invalid_names = ['Jo', 'A', 'Alex123', 'Test@Name']")
|
||||
|
||||
print()
|
||||
|
||||
|
||||
def main():
|
||||
"""Interactive data generator for FuncMage Chronicles."""
|
||||
print("🧙♀️ FuncMage Chronicles - Data Generator Helper 🧙♂️")
|
||||
print("=" * 50)
|
||||
print()
|
||||
|
||||
while True:
|
||||
print("Choose an option:")
|
||||
print("0. Generate data for Exercise 0 (Lambda Sanctum)")
|
||||
print("1. Generate data for Exercise 1 (Higher Realm)")
|
||||
print("2. Generate data for Exercise 2 (Memory Depths)")
|
||||
print("3. Generate data for Exercise 3 (Ancient Library)")
|
||||
print("4. Generate data for Exercise 4 (Master's Tower)")
|
||||
print("5. Generate data for ALL exercises")
|
||||
print("6. Generate custom mage data")
|
||||
print("7. Generate custom artifact data")
|
||||
print("q. Quit")
|
||||
print()
|
||||
|
||||
choice = input("Enter your choice: ").strip().lower()
|
||||
|
||||
if choice == 'q':
|
||||
print("May your functions be pure and your closures be strong! 🌟")
|
||||
break
|
||||
elif choice in ['0', '1', '2', '3', '4']:
|
||||
FuncMageDataGenerator.print_exercise_data(int(choice))
|
||||
elif choice == '5':
|
||||
for i in range(5):
|
||||
FuncMageDataGenerator.print_exercise_data(i)
|
||||
elif choice == '6':
|
||||
count = int(
|
||||
input("How many mages to generate? (default 5): ") or 5)
|
||||
print("mages =", FuncMageDataGenerator.generate_mages(count))
|
||||
print()
|
||||
elif choice == '7':
|
||||
count = int(
|
||||
input("How many artifacts to generate? (default 5): ") or 5)
|
||||
print(
|
||||
"artifacts =",
|
||||
FuncMageDataGenerator.generate_artifacts(count))
|
||||
print()
|
||||
else:
|
||||
print("Invalid choice. Please try again.")
|
||||
print()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,4 +1,7 @@
|
||||
def artifact_sorter(artifacts: list[dict]) -> list[dict]:
|
||||
from typing import Any
|
||||
|
||||
|
||||
def artifact_sorter(artifacts: list[dict[Any, Any]]) -> list[dict[Any, Any]]:
|
||||
try:
|
||||
return sorted(artifacts, key=lambda artifact: artifact["power"])
|
||||
except KeyError as err:
|
||||
@@ -6,7 +9,9 @@ def artifact_sorter(artifacts: list[dict]) -> list[dict]:
|
||||
return artifacts
|
||||
|
||||
|
||||
def power_filter(mages: list[dict], min_power: int) -> list[dict]:
|
||||
def power_filter(
|
||||
mages: list[dict[Any, Any]], min_power: int
|
||||
) -> list[dict[Any, Any]]:
|
||||
try:
|
||||
return list(filter(lambda x: x["power"] >= min_power, mages))
|
||||
except KeyError as err:
|
||||
@@ -18,7 +23,7 @@ def spell_transformer(spells: list[str]) -> list[str]:
|
||||
return list(map(lambda x: "* " + x + " *", spells))
|
||||
|
||||
|
||||
def mage_stats(mages: list[dict]) -> dict:
|
||||
def mage_stats(mages: list[dict[Any, Any]]) -> dict[str, int | float]:
|
||||
try:
|
||||
max_power = max(mages, key=lambda mage: mage["power"])
|
||||
min_power = min(mages, key=lambda mage: mage["power"])
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
from typing import Callable
|
||||
from typing import Any, Callable
|
||||
|
||||
|
||||
def spell_combiner(spell1: Callable, spell2: Callable) -> Callable:
|
||||
def combiner(*args):
|
||||
def combiner(*args: Any) -> tuple[Any, Any]:
|
||||
return (spell1(*args), spell2(*args))
|
||||
|
||||
return combiner
|
||||
|
||||
|
||||
def power_amplifier(base_spell: Callable, multiplier: int) -> Callable:
|
||||
def multiplie(*args):
|
||||
def multiply(*args: Any) -> Any:
|
||||
return base_spell(*args) * multiplier
|
||||
|
||||
return multiplie
|
||||
return multiply
|
||||
|
||||
|
||||
def conditional_caster(condition: Callable, spell: Callable) -> Callable:
|
||||
def cond_res(*args, **kwargs):
|
||||
def cond_res(*args: Any, **kwargs: Any) -> Any:
|
||||
if condition(*args, **kwargs):
|
||||
return spell(args[0])
|
||||
else:
|
||||
@@ -26,7 +26,7 @@ def conditional_caster(condition: Callable, spell: Callable) -> Callable:
|
||||
|
||||
|
||||
def spell_sequence(spells: list[Callable]) -> Callable:
|
||||
def sequence(*args, **kwargs):
|
||||
def sequence(*args: Any, **kwargs: Any) -> list[Any]:
|
||||
return [res(*args, **kwargs) for res in spells]
|
||||
|
||||
return sequence
|
||||
@@ -56,7 +56,7 @@ def main() -> None:
|
||||
|
||||
print("\n=== power_amplifier ===")
|
||||
amplifier = power_amplifier(pow_2, 4)
|
||||
print(f"multiplie 5 pow_2 by 4: {amplifier(5)}")
|
||||
print(f"multiply 5 pow_2 by 4: {amplifier(5)}")
|
||||
|
||||
print("\n=== conditional_caster ===")
|
||||
caster = conditional_caster(isinstance, fireball)
|
||||
|
||||
@@ -34,7 +34,6 @@ def memory_vault() -> dict[str, Callable]:
|
||||
storage = {}
|
||||
|
||||
def store(to_store: dict[str, str]) -> None:
|
||||
nonlocal storage
|
||||
for data in to_store:
|
||||
storage[data] = to_store[data]
|
||||
|
||||
@@ -47,7 +46,7 @@ def memory_vault() -> dict[str, Callable]:
|
||||
return {"store": store, "recall": recall}
|
||||
|
||||
|
||||
def main():
|
||||
def main() -> None:
|
||||
print("===mage_counter===\n")
|
||||
count = mage_counter()
|
||||
print(f"1 : {count()}")
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from functools import lru_cache, reduce, partial, singledispatch
|
||||
import operator as op
|
||||
import re
|
||||
from typing import Callable, Any
|
||||
|
||||
|
||||
@@ -27,6 +26,7 @@ def partial_enchanter(base_enchantment: Callable) -> dict[str, Callable]:
|
||||
}
|
||||
|
||||
|
||||
@lru_cache
|
||||
def memoized_fibonacci(n: int) -> int:
|
||||
if n < 2:
|
||||
return n
|
||||
@@ -35,7 +35,7 @@ def memoized_fibonacci(n: int) -> int:
|
||||
|
||||
def spell_dispatcher() -> Callable:
|
||||
@singledispatch
|
||||
def basic(arg: Any) -> str:
|
||||
def basic(arg: Any) -> Any:
|
||||
return arg
|
||||
|
||||
@basic.register(int)
|
||||
@@ -47,7 +47,7 @@ def spell_dispatcher() -> Callable:
|
||||
return f"apply {arg}"
|
||||
|
||||
@basic.register(list)
|
||||
def basic_list(arg: list) -> str:
|
||||
def basic_list(arg: list[Any]) -> str:
|
||||
res = ""
|
||||
for cast in arg:
|
||||
res += f"cast {cast}\n"
|
||||
|
||||
+32
-22
@@ -5,7 +5,7 @@ from functools import wraps
|
||||
|
||||
def spell_timer(func: Callable) -> Callable:
|
||||
@wraps(func)
|
||||
def print_time(*args, **kwargs) -> Any:
|
||||
def print_time(*args: Any, **kwargs: Any) -> Any:
|
||||
print(f"Casting {func.__name__}")
|
||||
start = time.time()
|
||||
res = func(*args, **kwargs)
|
||||
@@ -16,27 +16,38 @@ def spell_timer(func: Callable) -> Callable:
|
||||
|
||||
|
||||
def power_validator(min_power: int) -> Callable:
|
||||
def check_power(power: int, func: Callable) -> str | Any:
|
||||
def check_power(func: Callable) -> str | Any:
|
||||
@wraps(func)
|
||||
def fn(*args: Any) -> str | Any:
|
||||
try:
|
||||
if power < min_power:
|
||||
if args[2] < min_power:
|
||||
return "Insufficient power for this spell"
|
||||
return func()
|
||||
except Exception:
|
||||
return func(*args)
|
||||
except Exception as err:
|
||||
print(err)
|
||||
return "invalid input"
|
||||
|
||||
return fn
|
||||
|
||||
return check_power
|
||||
|
||||
|
||||
def retry_spell(max_attempts: int) -> Callable:
|
||||
def try_spell(func: Callable) -> str | Any:
|
||||
@wraps(func)
|
||||
def fn(*args: Any) -> Any:
|
||||
for i in range(max_attempts):
|
||||
try:
|
||||
return func()
|
||||
return func(*args)
|
||||
except Exception:
|
||||
print(f"Spell failed, retrying... ({i + 1}/{max_attempts})")
|
||||
print(
|
||||
f"Spell failed, retrying... ({i + 1}/{max_attempts})"
|
||||
)
|
||||
continue
|
||||
return f"Spell casting failed after {max_attempts} attempts"
|
||||
|
||||
return fn
|
||||
|
||||
return try_spell
|
||||
|
||||
|
||||
@@ -45,34 +56,34 @@ class MageGuild:
|
||||
def validate_mage_name(name: str) -> bool:
|
||||
return len(name) >= 3 and all(x.isalpha() or x.isspace() for x in name)
|
||||
|
||||
@power_validator(10)
|
||||
def cast_spell(self, spell_name: str, power: int) -> str:
|
||||
def cast() -> str:
|
||||
return f"Successfully cast {spell_name} with {power} power"
|
||||
|
||||
validator = power_validator(10)
|
||||
return validator(power, cast)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
import time
|
||||
|
||||
@spell_timer
|
||||
def fireball() -> str:
|
||||
time.sleep(0.5)
|
||||
return "Fireball cast!"
|
||||
|
||||
def make_exception() -> None:
|
||||
raise Exception
|
||||
@retry_spell(3)
|
||||
def make_exception(exception: Exception) -> None:
|
||||
raise exception
|
||||
|
||||
guild = MageGuild()
|
||||
|
||||
print("===spell_timer===\n")
|
||||
timer = spell_timer(fireball)
|
||||
print(f"Result: {timer()}")
|
||||
print(f"Result: {fireball()}")
|
||||
|
||||
print("\n===power_validator===\n")
|
||||
validator = power_validator(10)
|
||||
print(f"Valid: {validator(15, fireball)}")
|
||||
print(f"Invalid: {validator(5, fireball)}")
|
||||
print(f"Valid: {guild.cast_spell('meteorite de caca', 15)}")
|
||||
print(f"INvalid: {guild.cast_spell('meteorite de caca', 5)}")
|
||||
|
||||
print("\n===retry_spell===\n")
|
||||
retry = retry_spell(3)
|
||||
print(f"Valid: {retry(fireball)}")
|
||||
print(f"Invalid: {retry(make_exception)}")
|
||||
print(f"Invalid: {make_exception(Exception())}")
|
||||
|
||||
print("\n======MageGuild======\n")
|
||||
print("\n===validate_mage_name===\n")
|
||||
@@ -84,7 +95,6 @@ def main() -> None:
|
||||
)
|
||||
|
||||
print("\n===cast_spell===\n")
|
||||
guild = MageGuild()
|
||||
print(f"Valid: {guild.cast_spell('Lightning', 15)}")
|
||||
print(f"Invalid: {guild.cast_spell('Lightning', 5)}")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user