From cad1fdcab56c535c8f37b3c35bb0adccb0a83de3 Mon Sep 17 00:00:00 2001 From: dlee-bq <325002271+dlee-bq@users.noreply.github.com> Date: Sat, 24 Oct 2026 01:12:31 -0700 Subject: [PATCH] Target Python 3.11 in ruff and ty for cli, core, mcp_server, platform_api, cookiecutter With ruff target-version py310 and ty python-version 3.10, both tools reject an unconditional `import tomllib`: ty reports it as unresolved (exit 1) and ruff's isort classifies it as third-party. Raise the targets in the projects that now import tomllib directly, and in the root ruff.toml that governs dev_install.py. - ruff target-version = "py311" and ty python-version = "3.11" in cli, core, mcp_server, platform_api, and cookiecutter; root ruff.toml target-version = "py311" - UP042: OutputMode, ChartLifecycle, MCPType, and HTTPMethod become StrEnum; every consumer uses .value or == comparisons, so only str() and format() output change - UP017: datetime.timezone.utc -> datetime.UTC (ruff autofix) in the cli dispatchers, the cli test generator, and a core test --- cli/openbb_cli/codegen/test_gen.py | 5 +++-- cli/openbb_cli/dispatchers/http.py | 4 ++-- cli/openbb_cli/dispatchers/socrata.py | 4 ++-- cli/openbb_cli/dispatchers/spec.py | 4 ++-- cli/openbb_cli/models/settings.py | 4 ++-- cli/pyproject.toml | 4 ++-- cookiecutter/pyproject.toml | 4 ++-- openbb_platform/core/openbb_core/app/charting/hooks.py | 4 ++-- openbb_platform/core/pyproject.toml | 4 ++-- openbb_platform/core/tests/provider/utils/test_helpers.py | 8 +++----- .../mcp_server/openbb_mcp_server/models/mcp_config.py | 6 +++--- openbb_platform/extensions/mcp_server/pyproject.toml | 4 ++-- openbb_platform/extensions/platform_api/pyproject.toml | 4 ++-- ruff.toml | 2 +- 14 files changed, 30 insertions(+), 31 deletions(-) diff --git a/cli/openbb_cli/codegen/test_gen.py b/cli/openbb_cli/codegen/test_gen.py index 6492789d150..89467eb354b 100644 --- a/cli/openbb_cli/codegen/test_gen.py +++ b/cli/openbb_cli/codegen/test_gen.py @@ -3,6 +3,7 @@ from __future__ import annotations from dataclasses import dataclass +from datetime import UTC from typing import TYPE_CHECKING, Any from openbb_cli.codegen.pydantic_gen import safe_field_name @@ -288,7 +289,7 @@ def _spec_supplied_value(param: dict[str, Any]) -> Any: def _refresh_date_shape(name: str, value: Any) -> Any: """Replace an aged date-shaped string with an equivalent current date.""" import re - from datetime import date, datetime, timedelta, timezone + from datetime import date, datetime, timedelta if not isinstance(value, str): return value @@ -298,7 +299,7 @@ def _refresh_date_shape(name: str, value: Any) -> Any: today = date.today() return str(today - timedelta(days=30) if is_start else today) if re.fullmatch(r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z?", value): - now = datetime.now(timezone.utc).replace(microsecond=0) + now = datetime.now(UTC).replace(microsecond=0) chosen = (now - timedelta(days=30)) if is_start else now return chosen.isoformat().replace("+00:00", "Z") return value diff --git a/cli/openbb_cli/dispatchers/http.py b/cli/openbb_cli/dispatchers/http.py index 6ff9a933a33..7a795fd2aa6 100644 --- a/cli/openbb_cli/dispatchers/http.py +++ b/cli/openbb_cli/dispatchers/http.py @@ -7,7 +7,7 @@ import inspect import json import re import warnings -from datetime import datetime, timezone +from datetime import UTC, datetime from time import perf_counter_ns from typing import Any @@ -818,7 +818,7 @@ class HttpDispatcher: wire_request = request if time_axis is not None or fetch_all: wire_request = _request_with_page_size_limit(request) - timestamp = datetime.now(timezone.utc) + timestamp = datetime.now(UTC) start_ns = perf_counter_ns() try: url, body_or_query = self._resolve_url( diff --git a/cli/openbb_cli/dispatchers/socrata.py b/cli/openbb_cli/dispatchers/socrata.py index ac8a130e457..50bbe77563f 100644 --- a/cli/openbb_cli/dispatchers/socrata.py +++ b/cli/openbb_cli/dispatchers/socrata.py @@ -9,7 +9,7 @@ import re import urllib.error import urllib.parse import urllib.request -from datetime import datetime, timezone +from datetime import UTC, datetime from pathlib import Path from typing import Any @@ -1029,7 +1029,7 @@ def build_socrata_spec( return { "version": SPEC_VERSION, - "generated_at": datetime.now(timezone.utc).isoformat(), + "generated_at": datetime.now(UTC).isoformat(), "generator": _generator_identifier(), "source_url": story_source, "api_version": "socrata-soda-2.1", diff --git a/cli/openbb_cli/dispatchers/spec.py b/cli/openbb_cli/dispatchers/spec.py index 406a7f4c0a2..fe79aaf66b3 100644 --- a/cli/openbb_cli/dispatchers/spec.py +++ b/cli/openbb_cli/dispatchers/spec.py @@ -6,7 +6,7 @@ import argparse import hashlib import json import re -from datetime import datetime, timezone +from datetime import UTC, datetime from importlib.metadata import ( PackageNotFoundError, version as _pkg_version, @@ -434,7 +434,7 @@ def build_spec_document( _strip_fixed_headers(commands, headers) doc = { "version": SPEC_VERSION, - "generated_at": datetime.now(timezone.utc).isoformat(), + "generated_at": datetime.now(UTC).isoformat(), "generator": _generator_identifier(), "source_url": source_url or "", "api_version": str(openapi.get("openapi") or openapi.get("swagger") or ""), diff --git a/cli/openbb_cli/models/settings.py b/cli/openbb_cli/models/settings.py index e855e7e02d7..70e318f9e13 100644 --- a/cli/openbb_cli/models/settings.py +++ b/cli/openbb_cli/models/settings.py @@ -1,7 +1,7 @@ """Settings model.""" import os -from enum import Enum +from enum import Enum, StrEnum from typing import Any, Literal from zoneinfo import available_timezones @@ -16,7 +16,7 @@ from openbb_cli.config.constants import AVAILABLE_FLAIRS, ENV_FILE_SETTINGS VERSION = get_package_version("openbb-cli") -class OutputMode(str, Enum): +class OutputMode(StrEnum): """Output mode for displaying results.""" rich = "rich" diff --git a/cli/pyproject.toml b/cli/pyproject.toml index 77bdc8ef8cc..f75bd7227ab 100644 --- a/cli/pyproject.toml +++ b/cli/pyproject.toml @@ -49,7 +49,7 @@ include = [ [tool.ruff] line-length = 88 -target-version = "py310" +target-version = "py311" fix = true [tool.ruff.lint] @@ -124,7 +124,7 @@ convention = "numpy" [tool.ty] [tool.ty.environment] -python-version = "3.10" +python-version = "3.11" [tool.ty.src] include = ["openbb_cli"] diff --git a/cookiecutter/pyproject.toml b/cookiecutter/pyproject.toml index c468b143273..ae8edc93e36 100644 --- a/cookiecutter/pyproject.toml +++ b/cookiecutter/pyproject.toml @@ -46,7 +46,7 @@ include = ["openbb_cookiecutter", "tests", "README.md", "pyproject.toml"] [tool.ruff] line-length = 88 -target-version = "py310" +target-version = "py311" fix = true extend-exclude = ["openbb_cookiecutter/template"] @@ -74,7 +74,7 @@ convention = "numpy" [tool.ty] [tool.ty.environment] -python-version = "3.10" +python-version = "3.11" [tool.ty.src] include = ["openbb_cookiecutter"] diff --git a/openbb_platform/core/openbb_core/app/charting/hooks.py b/openbb_platform/core/openbb_core/app/charting/hooks.py index c15eeb5f819..e838d9adfcb 100644 --- a/openbb_platform/core/openbb_core/app/charting/hooks.py +++ b/openbb_platform/core/openbb_core/app/charting/hooks.py @@ -8,7 +8,7 @@ chart is requested from the Python interface, the REST API, the CLI, or MCP. from __future__ import annotations from dataclasses import dataclass, field -from enum import Enum +from enum import StrEnum from typing import Any from importlib_metadata import entry_points @@ -16,7 +16,7 @@ from importlib_metadata import entry_points CHARTING_HOOKS_GROUP = "openbb_charting_hooks" -class ChartLifecycle(str, Enum): +class ChartLifecycle(StrEnum): """Stages a chart passes through during creation.""" RESOLVE_DATA = "resolve_data" diff --git a/openbb_platform/core/pyproject.toml b/openbb_platform/core/pyproject.toml index e6e45a2085f..9af4a1b25c4 100644 --- a/openbb_platform/core/pyproject.toml +++ b/openbb_platform/core/pyproject.toml @@ -56,7 +56,7 @@ include = [ [tool.ruff] line-length = 88 -target-version = "py310" +target-version = "py311" fix = true extend-exclude = [ "openbb/package", @@ -131,7 +131,7 @@ convention = "numpy" [tool.ty] [tool.ty.environment] -python-version = "3.10" +python-version = "3.11" [tool.ty.src] include = ["openbb_core", "openbb"] diff --git a/openbb_platform/core/tests/provider/utils/test_helpers.py b/openbb_platform/core/tests/provider/utils/test_helpers.py index 4c3f0ffb238..b24cd52d0b5 100644 --- a/openbb_platform/core/tests/provider/utils/test_helpers.py +++ b/openbb_platform/core/tests/provider/utils/test_helpers.py @@ -164,25 +164,23 @@ def test_safe_fromtimestamp_negative_on_non_windows(): def test_safe_fromtimestamp_windows_negative_branch(monkeypatch): """Force the os.name=='nt' branch to test the timedelta fallback path.""" - from datetime import timezone from openbb_core.provider.utils import helpers monkeypatch.setattr(helpers, "os", type("FakeOs", (), {"name": "nt"})) - out = helpers.safe_fromtimestamp(-3600, tz=timezone.utc) + out = helpers.safe_fromtimestamp(-3600, tz=dt.UTC) assert out.year == 1969 def test_safe_fromtimestamp_windows_non_negative_uses_datetime_fromtimestamp( monkeypatch, ): - from datetime import timezone from openbb_core.provider.utils import helpers monkeypatch.setattr(helpers, "os", type("FakeOs", (), {"name": "nt"})) - out = helpers.safe_fromtimestamp(0, tz=timezone.utc) - assert out == dt.datetime(1970, 1, 1, tzinfo=timezone.utc) + out = helpers.safe_fromtimestamp(0, tz=dt.UTC) + assert out == dt.datetime(1970, 1, 1, tzinfo=dt.UTC) def test_check_item_suggests_similar(): diff --git a/openbb_platform/extensions/mcp_server/openbb_mcp_server/models/mcp_config.py b/openbb_platform/extensions/mcp_server/openbb_mcp_server/models/mcp_config.py index 778d875d037..d74cc2cb646 100644 --- a/openbb_platform/extensions/mcp_server/openbb_mcp_server/models/mcp_config.py +++ b/openbb_platform/extensions/mcp_server/openbb_mcp_server/models/mcp_config.py @@ -1,7 +1,7 @@ """Validation models for MCP configuration structures.""" import re -from enum import Enum +from enum import StrEnum from typing import Any from fastmcp.utilities.logging import get_logger @@ -10,7 +10,7 @@ from pydantic import BaseModel, Field, field_validator, model_validator logger = get_logger(__name__) -class MCPType(str, Enum): +class MCPType(StrEnum): """Valid MCP type values.""" TOOL = "tool" @@ -18,7 +18,7 @@ class MCPType(str, Enum): RESOURCE_TEMPLATE = "resource_template" -class HTTPMethod(str, Enum): +class HTTPMethod(StrEnum): """Valid HTTP methods for route configuration.""" GET = "GET" diff --git a/openbb_platform/extensions/mcp_server/pyproject.toml b/openbb_platform/extensions/mcp_server/pyproject.toml index a51323ffd92..c96350dcca8 100644 --- a/openbb_platform/extensions/mcp_server/pyproject.toml +++ b/openbb_platform/extensions/mcp_server/pyproject.toml @@ -45,7 +45,7 @@ include = [ [tool.ruff] line-length = 88 -target-version = "py310" +target-version = "py311" fix = true [tool.ruff.lint] @@ -116,7 +116,7 @@ convention = "numpy" [tool.ty] [tool.ty.environment] -python-version = "3.10" +python-version = "3.11" [tool.ty.src] include = ["openbb_mcp_server"] diff --git a/openbb_platform/extensions/platform_api/pyproject.toml b/openbb_platform/extensions/platform_api/pyproject.toml index 005a4787cdc..40a8e03855d 100644 --- a/openbb_platform/extensions/platform_api/pyproject.toml +++ b/openbb_platform/extensions/platform_api/pyproject.toml @@ -40,7 +40,7 @@ include = [ [tool.ruff] line-length = 88 -target-version = "py310" +target-version = "py311" fix = true [tool.ruff.lint] @@ -111,7 +111,7 @@ convention = "numpy" [tool.ty] [tool.ty.environment] -python-version = "3.10" +python-version = "3.11" [tool.ty.src] include = ["openbb_platform_api"] diff --git a/ruff.toml b/ruff.toml index cb5fed8df3d..c8bd6695fcb 100644 --- a/ruff.toml +++ b/ruff.toml @@ -3,7 +3,7 @@ exclude = [ "^cookiecutter/*", ] line-length = 88 -target-version = "py310" +target-version = "py311" fix = true [format]