Refactor and update structure #20

Merged
Berack96 merged 22 commits from 16-refactoring-e-sanity-check into main 2025-10-08 16:21:10 +02:00
2 changed files with 12 additions and 35 deletions
Showing only changes of commit 07ab380669 - Show all commits

View File

@@ -19,7 +19,7 @@ def aggregate_history_prices(prices: dict[str, list[Price]]) -> list[Price]:
timestamped_prices.setdefault(time, []).append(price) timestamped_prices.setdefault(time, []).append(price)
# Ora aggregiamo i prezzi per ogni ora # Ora aggregiamo i prezzi per ogni ora
aggregated_prices = [] aggregated_prices: list[Price] = []
for time, price_list in timestamped_prices.items(): for time, price_list in timestamped_prices.items():
price = Price() price = Price()
price.timestamp_ms = time price.timestamp_ms = time
@@ -47,8 +47,7 @@ def aggregate_product_info(products: dict[str, list[ProductInfo]]) -> list[Produ
symbols_infos.setdefault(product.symbol, []).append(product) symbols_infos.setdefault(product.symbol, []).append(product)
# Aggregazione per ogni symbol # Aggregazione per ogni symbol
sources = list(products.keys()) aggregated_products: list[ProductInfo] = []
aggregated_products = []
for symbol, product_list in symbols_infos.items(): for symbol, product_list in symbols_infos.items():
product = ProductInfo() product = ProductInfo()
@@ -65,27 +64,3 @@ def aggregate_product_info(products: dict[str, list[ProductInfo]]) -> list[Produ
aggregated_products.append(product) aggregated_products.append(product)
return aggregated_products return aggregated_products
def _calculate_confidence(products: list[ProductInfo], sources: list[str]) -> float:
"""Calcola un punteggio di confidenza 0-1"""
if not products:
return 0.0
score = 1.0
# Riduci score se pochi dati
if len(products) < 2:
score *= 0.7
# Riduci score se prezzi troppo diversi
prices = [p.price for p in products if p.price > 0]
if len(prices) > 1:
price_std = (max(prices) - min(prices)) / statistics.mean(prices)
if price_std > 0.05: # >5% variazione
score *= 0.8
# Riduci score se fonti sconosciute
unknown_sources = sum(1 for s in sources if s == "unknown")
if unknown_sources > 0:
score *= (1 - unknown_sources / len(sources))
return max(0.0, min(1.0, score))

View File

@@ -1,8 +1,8 @@
import inspect import inspect
import time import time
import traceback import traceback
from typing import Callable, Generic, Iterable, Type, TypeVar from typing import Any, Callable, Generic, TypeVar
from agno.utils.log import log_info, log_warning from agno.utils.log import log_info, log_warning #type: ignore
W = TypeVar("W") W = TypeVar("W")
T = TypeVar("T") T = TypeVar("T")
@@ -50,6 +50,7 @@ class WrapperHandler(Generic[W]):
log_info(f"{inspect.getsource(func).strip()} {inspect.getclosurevars(func).nonlocals}") log_info(f"{inspect.getsource(func).strip()} {inspect.getclosurevars(func).nonlocals}")
copilot-pull-request-reviewer[bot] commented 2025-10-05 19:33:31 +02:00 (Migrated from github.com)
Review

The variable 'error' is initialized but may be used uninitialized if no exception occurs in the while loop before the final raise statement.

The variable 'error' is initialized but may be used uninitialized if no exception occurs in the while loop before the final raise statement.
copilot-pull-request-reviewer[bot] commented 2025-10-05 21:18:36 +02:00 (Migrated from github.com)
Review

[nitpick] The variable 'error' is initialized but may not be used if no exceptions occur in the loop. Consider initializing it only when needed or using a more descriptive default value.


[nitpick] The variable 'error' is initialized but may not be used if no exceptions occur in the loop. Consider initializing it only when needed or using a more descriptive default value. ```suggestion ```
iterations = 0 iterations = 0
error = ""
while iterations < len(self.wrappers): while iterations < len(self.wrappers):
wrapper = self.wrappers[self.index] wrapper = self.wrappers[self.index]
wrapper_name = wrapper.__class__.__name__ wrapper_name = wrapper.__class__.__name__
@@ -89,13 +90,14 @@ class WrapperHandler(Generic[W]):
""" """
log_info(f"{inspect.getsource(func).strip()} {inspect.getclosurevars(func).nonlocals}") log_info(f"{inspect.getsource(func).strip()} {inspect.getclosurevars(func).nonlocals}")
copilot-pull-request-reviewer[bot] commented 2025-10-05 19:33:31 +02:00 (Migrated from github.com)
Review

The variable 'error' is initialized but may be used uninitialized if no exceptions occur in the for loop before checking if results is empty.

        error = "No error captured"
The variable 'error' is initialized but may be used uninitialized if no exceptions occur in the for loop before checking if results is empty. ```suggestion error = "No error captured" ```
results = {} results: dict[str, T] = {}
error = ""
for wrapper in self.wrappers: for wrapper in self.wrappers:
wrapper_name = wrapper.__class__.__name__ wrapper_name = wrapper.__class__.__name__
try: try:
result = func(wrapper) result = func(wrapper)
log_info(f"{wrapper_name} succeeded") log_info(f"{wrapper_name} succeeded")
results[wrapper.__class__] = result results[wrapper_name] = result
except Exception as e: except Exception as e:
error = WrapperHandler.__concise_error(e) error = WrapperHandler.__concise_error(e)
log_warning(f"{wrapper_name} failed: {error}") log_warning(f"{wrapper_name} failed: {error}")
@@ -104,7 +106,7 @@ class WrapperHandler(Generic[W]):
return results return results
@staticmethod @staticmethod
def __check(wrappers: list[W]) -> bool: def __check(wrappers: list[Any]) -> bool:
return all(w.__class__ is type for w in wrappers) return all(w.__class__ is type for w in wrappers)
@staticmethod @staticmethod
@@ -113,13 +115,13 @@ class WrapperHandler(Generic[W]):
return f"{e} [\"{last_frame.filename}\", line {last_frame.lineno}]" return f"{e} [\"{last_frame.filename}\", line {last_frame.lineno}]"
@staticmethod @staticmethod
def build_wrappers(constructors: Iterable[Type[W]], try_per_wrapper: int = 3, retry_delay: int = 2, kwargs: dict | None = None) -> 'WrapperHandler[W]': def build_wrappers(constructors: list[type[W]], try_per_wrapper: int = 3, retry_delay: int = 2, kwargs: dict[str, Any] | None = None) -> 'WrapperHandler[W]':
""" """
Builds a WrapperHandler instance with the given wrapper constructors. Builds a WrapperHandler instance with the given wrapper constructors.
It attempts to initialize each wrapper and logs a warning if any cannot be initialized. It attempts to initialize each wrapper and logs a warning if any cannot be initialized.
Only successfully initialized wrappers are included in the handler. Only successfully initialized wrappers are included in the handler.
Args: Args:
constructors (Iterable[Type[W]]): An iterable of wrapper classes to instantiate. e.g. [WrapperA, WrapperB] constructors (list[type[W]]): An iterable of wrapper classes to instantiate. e.g. [WrapperA, WrapperB]
try_per_wrapper (int): Number of retries per wrapper before switching to the next. try_per_wrapper (int): Number of retries per wrapper before switching to the next.
retry_delay (int): Delay in seconds between retries. retry_delay (int): Delay in seconds between retries.
kwargs (dict | None): Optional dictionary with keyword arguments common to all wrappers. kwargs (dict | None): Optional dictionary with keyword arguments common to all wrappers.
@@ -130,7 +132,7 @@ class WrapperHandler(Generic[W]):
""" """
assert WrapperHandler.__check(constructors), f"All constructors must be classes. Received: {constructors}" assert WrapperHandler.__check(constructors), f"All constructors must be classes. Received: {constructors}"
result = [] result: list[W] = []
for wrapper_class in constructors: for wrapper_class in constructors:
try: try:
wrapper = wrapper_class(**(kwargs or {})) wrapper = wrapper_class(**(kwargs or {}))