From a220b6bd46b65209bb17b895b7d8db3e528048f4 Mon Sep 17 00:00:00 2001 From: dlee-bq <325002271+dlee-bq@users.noreply.github.com> Date: Sat, 17 Oct 2026 12:09:36 -0700 Subject: [PATCH] - example.py: mark the base Example.scope field frozen so the Literal[api]/Literal[python] subclass overrides are covariant read-only narrowings. Subclass fields stay writable at runtime. - method_definition.py, options_chains.py: pydantic 2.14 types FieldInfo.annotation as TypeForm[Any] | None, which ty rejects in Union[]/Annotated[] and where is expected; bind it as Any. Use FieldInfo.get_default(call_default_factory=True) instead of calling the default_factory union directly. - economy_views.py: read data/obbject_item without None defaults in the IMF shipping views. charting always sets obbject_item, and data is only popped when present and not None.- finra, jodi, eia: annotate @asynccontextmanager/@contextmanager functions with AsyncGenerator/Generator instead of the deprecated AsyncIterator/Iterator return types. - charting: cast the darts forecast dataset to TimeSeries before indexing so .all_values resolves instead of hitting ndarray. - fred, imf, nasdaq, sec, tmx: turn off invalid-attribute-override and invalid-mutable-override for models/** only, following the cboe precedent. Provider models extend the standard models by narrowing query params to Literals or widening fields to Optional, which these rules flag by design. --- openbb_platform/core/openbb_core/app/model/example.py | 2 +- .../app/static/package_builder/method_definition.py | 4 ++-- .../provider/standard_models/options_chains.py | 2 +- .../extensions/economy/openbb_economy/economy_views.py | 8 ++++---- .../charting/openbb_charting/core/openbb_figure.py | 5 ++++- openbb_platform/providers/eia/openbb_us_eia/browsers.py | 4 ++-- .../providers/finra/openbb_finra/utils/client.py | 8 ++++---- openbb_platform/providers/fred/pyproject.toml | 7 +++++++ openbb_platform/providers/imf/pyproject.toml | 7 +++++++ .../providers/jodi/openbb_jodi/utils/helpers.py | 4 ++-- openbb_platform/providers/nasdaq/pyproject.toml | 7 +++++++ openbb_platform/providers/sec/pyproject.toml | 7 +++++++ openbb_platform/providers/tmx/pyproject.toml | 7 +++++++ 13 files changed, 55 insertions(+), 17 deletions(-) diff --git a/openbb_platform/core/openbb_core/app/model/example.py b/openbb_platform/core/openbb_core/app/model/example.py index 6a0abfb38fca..b3f631b21481 100644 --- a/openbb_platform/core/openbb_core/app/model/example.py +++ b/openbb_platform/core/openbb_core/app/model/example.py @@ -18,7 +18,7 @@ class Example(BaseModel): """Example model.""" - scope: str + scope: str = Field(frozen=True) model_config = ConfigDict(validate_assignment=True) diff --git a/openbb_platform/core/openbb_core/app/static/package_builder/method_definition.py b/openbb_platform/core/openbb_core/app/static/package_builder/method_definition.py index c9a0a06bf874..d73cb47bc4b5 100644 --- a/openbb_platform/core/openbb_core/app/static/package_builder/method_definition.py +++ b/openbb_platform/core/openbb_core/app/static/package_builder/method_definition.py @@ -791,7 +791,7 @@ def format_params( # noqa: PLR0912 qp_model := MethodDefinition.query_params_model(param.annotation) ) is not None: for field_name, field in qp_model.model_fields.items(): - field_anno = field.annotation + field_anno: Any = field.annotation new_type = MethodDefinition.get_expanded_type( field_name, None, field_anno ) @@ -807,7 +807,7 @@ def format_params( # noqa: PLR0912 if field.is_required(): field_default: Any = Parameter.empty elif field.default_factory is not None: - field_default = field.default_factory() + field_default = field.get_default(call_default_factory=True) else: field_default = field.default formatted[field_name] = Parameter( diff --git a/openbb_platform/core/openbb_core/provider/standard_models/options_chains.py b/openbb_platform/core/openbb_core/provider/standard_models/options_chains.py index 6097f2c65bfb..c889b7739da6 100644 --- a/openbb_platform/core/openbb_core/provider/standard_models/options_chains.py +++ b/openbb_platform/core/openbb_core/provider/standard_models/options_chains.py @@ -390,7 +390,7 @@ def __get_pydantic_json_schema__( row_fields: dict[str, Any] = {} for field_name, field_info in cls.model_fields.items(): - annotation = field_info.annotation + annotation: Any = field_info.annotation inner = ( get_args(annotation)[0] if get_origin(annotation) is list diff --git a/openbb_platform/extensions/economy/openbb_economy/economy_views.py b/openbb_platform/extensions/economy/openbb_economy/economy_views.py index d6258c303b91..8172c9d7f9c0 100644 --- a/openbb_platform/extensions/economy/openbb_economy/economy_views.py +++ b/openbb_platform/extensions/economy/openbb_economy/economy_views.py @@ -567,9 +567,9 @@ def economy_shipping_chokepoint_info( or getattr(kwargs["charting_settings"], "chart_style", "dark") ) data = ( - kwargs.pop("data", None) + kwargs.pop("data") if "data" in kwargs and kwargs["data"] is not None - else kwargs.get("obbject_item") + else kwargs["obbject_item"] ) fig = plot_chokepoint_annual_avg_vessels(data, theme=theme) fig.update_layout( @@ -601,9 +601,9 @@ def economy_shipping_port_info( raise RuntimeError("Unable to import the required module.") from e data = ( - kwargs.pop("data", None) + kwargs.pop("data") if "data" in kwargs and kwargs["data"] is not None - else kwargs.get("obbject_item") + else kwargs["obbject_item"] ) fig = plot_port_info_map(data) fig.update_layout( diff --git a/openbb_platform/obbject_extensions/charting/openbb_charting/core/openbb_figure.py b/openbb_platform/obbject_extensions/charting/openbb_charting/core/openbb_figure.py index 9d8eec71ef34..9c5ce83055c4 100644 --- a/openbb_platform/obbject_extensions/charting/openbb_charting/core/openbb_figure.py +++ b/openbb_platform/obbject_extensions/charting/openbb_charting/core/openbb_figure.py @@ -11,6 +11,7 @@ Literal, TypeVar, Union, + cast, ) from warnings import warn @@ -325,7 +326,9 @@ def _validate_x(data: ndarray | Series | type[TimeSeriesT]): if forecast: # pragma: no cover - darts forecast path (darts is an optional dependency) components = list(dataset.components[:4]) # ty: ignore[unresolved-attribute] values = ( - dataset[components].all_values(copy=False).flatten(order="F") + cast("TimeSeries", dataset)[components] + .all_values(copy=False) + .flatten(order="F") ) n_components = len(components) n_entries = len(values) // n_components diff --git a/openbb_platform/providers/eia/openbb_us_eia/browsers.py b/openbb_platform/providers/eia/openbb_us_eia/browsers.py index 76187997081b..04c16d7546c9 100644 --- a/openbb_platform/providers/eia/openbb_us_eia/browsers.py +++ b/openbb_platform/providers/eia/openbb_us_eia/browsers.py @@ -2,7 +2,7 @@ import re import threading -from collections.abc import AsyncIterator +from collections.abc import AsyncGenerator from contextlib import asynccontextmanager from pathlib import Path from typing import Annotated, Any @@ -2062,7 +2062,7 @@ async def render_browser( @asynccontextmanager -async def lifespan(_app) -> AsyncIterator[None]: +async def lifespan(_app) -> AsyncGenerator[None, None]: """Warm the proxy cache for the lifetime of the API, cleaning up on shutdown.""" _schedule_warm() try: diff --git a/openbb_platform/providers/finra/openbb_finra/utils/client.py b/openbb_platform/providers/finra/openbb_finra/utils/client.py index f6aab09da18d..448aff4a0e9c 100644 --- a/openbb_platform/providers/finra/openbb_finra/utils/client.py +++ b/openbb_platform/providers/finra/openbb_finra/utils/client.py @@ -1,6 +1,6 @@ """HTTP transport for the FINRA data services.""" -from collections.abc import AsyncIterator, Awaitable, Callable +from collections.abc import AsyncGenerator, Awaitable, Callable from contextlib import asynccontextmanager from typing import Any @@ -243,7 +243,7 @@ async def partitions(self, group: str, dataset: str) -> list[list[str]]: @asynccontextmanager -async def query_api_session() -> AsyncIterator[QueryApiSession]: +async def query_api_session() -> AsyncGenerator[QueryApiSession, None]: """Open a session on the public FINRA Query API. Yields @@ -412,7 +412,7 @@ async def _trace_token(session: Any) -> str: @asynccontextmanager -async def trace_session() -> AsyncIterator[TraceSession]: +async def trace_session() -> AsyncGenerator[TraceSession, None]: """Open a session on the public TRACE data service. Yields @@ -590,7 +590,7 @@ async def static_data(self, security_ids: list[str]) -> list[dict]: @asynccontextmanager -async def market_data_session() -> AsyncIterator[MarketDataSession]: +async def market_data_session() -> AsyncGenerator[MarketDataSession, None]: """Open a seeded session on the FINRA Market Data Center. Yields diff --git a/openbb_platform/providers/fred/pyproject.toml b/openbb_platform/providers/fred/pyproject.toml index f59f66f13470..1a4ea8a5a274 100644 --- a/openbb_platform/providers/fred/pyproject.toml +++ b/openbb_platform/providers/fred/pyproject.toml @@ -83,6 +83,13 @@ exclude = ["tests", "integration"] [tool.ty.rules] unresolved-import = "warn" +[[tool.ty.overrides]] +include = ["openbb_fred/models/**"] + +[tool.ty.overrides.rules] +invalid-attribute-override = "ignore" +invalid-mutable-override = "ignore" + [tool.coverage.run] branch = true source = ["openbb_fred"] diff --git a/openbb_platform/providers/imf/pyproject.toml b/openbb_platform/providers/imf/pyproject.toml index 3861c4ea40ea..2edf42d25e86 100644 --- a/openbb_platform/providers/imf/pyproject.toml +++ b/openbb_platform/providers/imf/pyproject.toml @@ -110,6 +110,13 @@ exclude = ["tests", "integration", "openbb_imf/utils/generate_cache.py"] [tool.ty.rules] unresolved-import = "ignore" +[[tool.ty.overrides]] +include = ["openbb_imf/models/**"] + +[tool.ty.overrides.rules] +invalid-attribute-override = "ignore" +invalid-mutable-override = "ignore" + [tool.pytest.ini_options] testpaths = ["tests"] addopts = "-q --strict-markers" diff --git a/openbb_platform/providers/jodi/openbb_jodi/utils/helpers.py b/openbb_platform/providers/jodi/openbb_jodi/utils/helpers.py index e9247761c244..acee0ba4c80e 100644 --- a/openbb_platform/providers/jodi/openbb_jodi/utils/helpers.py +++ b/openbb_platform/providers/jodi/openbb_jodi/utils/helpers.py @@ -14,7 +14,7 @@ if TYPE_CHECKING: import asyncio # noqa - from collections.abc import Iterator, Mapping # noqa + from collections.abc import Generator, Mapping # noqa from datetime import date as dateType # noqa from pathlib import Path # noqa from typing import IO # noqa @@ -361,7 +361,7 @@ def bump_checked_at(table: str, snapshot: dict) -> dict: @contextmanager -def open_archive_csv(path: "Path") -> "Iterator": +def open_archive_csv(path: "Path") -> "Generator": """Open the CSV stream inside a raw source file, unzipping when needed.""" import zipfile diff --git a/openbb_platform/providers/nasdaq/pyproject.toml b/openbb_platform/providers/nasdaq/pyproject.toml index d414acadad83..e5677d7319dd 100644 --- a/openbb_platform/providers/nasdaq/pyproject.toml +++ b/openbb_platform/providers/nasdaq/pyproject.toml @@ -77,6 +77,13 @@ exclude = ["tests", "integration"] [tool.ty.rules] unresolved-import = "ignore" +[[tool.ty.overrides]] +include = ["openbb_nasdaq/models/**"] + +[tool.ty.overrides.rules] +invalid-attribute-override = "ignore" +invalid-mutable-override = "ignore" + [tool.pytest.ini_options] testpaths = ["tests"] addopts = "-q --strict-markers" diff --git a/openbb_platform/providers/sec/pyproject.toml b/openbb_platform/providers/sec/pyproject.toml index 87cfaae1f13c..e55536257b6f 100644 --- a/openbb_platform/providers/sec/pyproject.toml +++ b/openbb_platform/providers/sec/pyproject.toml @@ -90,6 +90,13 @@ exclude = ["tests", "integration"] [tool.ty.rules] unresolved-import = "ignore" +[[tool.ty.overrides]] +include = ["openbb_sec/models/**"] + +[tool.ty.overrides.rules] +invalid-attribute-override = "ignore" +invalid-mutable-override = "ignore" + [tool.pytest.ini_options] testpaths = ["tests"] addopts = "-q --strict-markers" diff --git a/openbb_platform/providers/tmx/pyproject.toml b/openbb_platform/providers/tmx/pyproject.toml index ee3a9f132ab5..47758e9f8487 100644 --- a/openbb_platform/providers/tmx/pyproject.toml +++ b/openbb_platform/providers/tmx/pyproject.toml @@ -91,6 +91,13 @@ exclude = ["tests", "integration"] [tool.ty.rules] unresolved-import = "warn" +[[tool.ty.overrides]] +include = ["openbb_tmx/models/**"] + +[tool.ty.overrides.rules] +invalid-attribute-override = "ignore" +invalid-mutable-override = "ignore" + [tool.coverage.report] exclude_lines = ["pragma: no cover", "if TYPE_CHECKING:", "raise NotImplementedError", "@overload"]