Skip to content

fix(helpers): fix type annotation bug: np.arraynp.ndarray in helpers.py (TypeError on Python 3.11+) - #95

Open
nervgh wants to merge 2 commits into
masterfrom
fix/type-anno-bug
Open

fix(helpers): fix type annotation bug: np.arraynp.ndarray in helpers.py (TypeError on Python 3.11+)#95
nervgh wants to merge 2 commits into
masterfrom
fix/type-anno-bug

Conversation

@nervgh

@nervgh nervgh commented Jul 26, 2026

Copy link
Copy Markdown

Fix type annotation bug: np.arraynp.ndarray in helpers.py (TypeError on Python 3.11+)

Description

Two methods in okama/common/helpers/helpers.py use np.array (a function) in PEP 604 union type hints instead of np.ndarray (the actual type). On Python 3.11+ these annotations are evaluated eagerly at import time and crash with TypeError.

Background

In okama/common/helpers/helpers.py, class Frame has two methods annotated with list | np.array:

def get_portfolio_mean_return(cls, weights: list | np.array, ror: pd.DataFrame) -> float:
def get_portfolio_risk(cls, weights: list | np.array, assets_ror: pd.DataFrame) -> float:

np.array is a builtin_function_or_method, not a type. PEP 604's | operator requires both operands to be types. When Python evaluates list | np.array it calls list.__or__(np.array), which receives a non-type and raises:

TypeError: unsupported operand type(s) for |: 'type' and 'builtin_function_or_method'

The bug was introduced in v1.3.0 (May 2023) during a refactoring into common/helpers/. At that time the code used typing.Union[list, np.array]Union accepts any object and does not validate that it's a type, so the bug remained latent. When the codebase migrated to PEP 604 syntax in v1.5.0 (Python 3.10+) and then v2.0.0 (Python 3.11+), the bug became fatal — list | np.array is evaluated eagerly and crashes.

The bug has persisted unreleased through 11 releases up to the current v2.3.0. It went unnoticed because no other module in okama directly triggers import of these Frame methods. It manifests when external code (e.g. okama-mcp server) calls get_portfolio_mean_return or get_portfolio_risk.

Scope

  • Fix two type annotations in okama/common/helpers/helpers.py, replacing np.array with np.ndarray:
    • get_portfolio_mean_return (line 258)
    • get_portfolio_risk (line 386)
  • The function bodies are correct as-is — np.array() calls inside the body are valid runtime invocations and must not be changed.

Related


Patch applied

File: okama/okama/common/helpers/helpers.py

Method Before (bug) After (fix)
get_portfolio_mean_return weights: list | np.array weights: list | np.ndarray
get_portfolio_risk weights: list | np.array weights: list | np.ndarray

Validation:

  • Ruff — All checks passed!
  • Full test suite could not be run (no Poetry environment available), but the change is purely mechanical — swapping a function reference for a type reference in two type annotations, with zero logic changes.

Summary by Sourcery

Enhancements:

  • Update Frame.get_portfolio_mean_return and Frame.get_portfolio_risk signatures to use np.ndarray instead of the np.array factory in union type hints.

@nervgh

nervgh commented Jul 26, 2026

Copy link
Copy Markdown
Author

I came from okama-mcp with the error.

# python --version # Python 3.12.3

# uvx okama-mcp stdio # <-- my command

Installed 91 packages in 84ms
Traceback (most recent call last):
  File "/tmp/.tmpshlVOC/archive-v0/dgrAM591ZcXkBhCg/bin/okama-mcp", line 12, in <module>
    sys.exit(main())
             ^^^^^^
  File "/tmp/.tmpshlVOC/archive-v0/dgrAM591ZcXkBhCg/lib/python3.12/site-packages/okama_mcp/transport.py", line 57, in main
    from okama_mcp.server import mcp
  File "/tmp/.tmpshlVOC/archive-v0/dgrAM591ZcXkBhCg/lib/python3.12/site-packages/okama_mcp/server.py", line 37, in <module>
    register_all(mcp)
  File "/tmp/.tmpshlVOC/archive-v0/dgrAM591ZcXkBhCg/lib/python3.12/site-packages/okama_mcp/tools/__init__.py", line 14, in register_all
    from okama_mcp.tools import (
  File "/tmp/.tmpshlVOC/archive-v0/dgrAM591ZcXkBhCg/lib/python3.12/site-packages/okama_mcp/tools/asset.py", line 13, in <module>
    import okama as ok
  File "/tmp/.tmpshlVOC/archive-v0/dgrAM591ZcXkBhCg/lib/python3.12/site-packages/okama/__init__.py", line 27, in <module>
    from okama.asset_list import AssetList  # noqa: F401
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/tmp/.tmpshlVOC/archive-v0/dgrAM591ZcXkBhCg/lib/python3.12/site-packages/okama/asset_list.py", line 7, in <module>
    from okama.common.helpers.helpers import check_rolling_window
  File "/tmp/.tmpshlVOC/archive-v0/dgrAM591ZcXkBhCg/lib/python3.12/site-packages/okama/common/helpers/helpers.py", line 225, in <module>
    class Frame:
  File "/tmp/.tmpshlVOC/archive-v0/dgrAM591ZcXkBhCg/lib/python3.12/site-packages/okama/common/helpers/helpers.py", line 258, in Frame
    def get_portfolio_mean_return(cls, weights: list | np.array, ror: pd.DataFrame) -> float:
                                                ~~~~~^~~~~~~~~~
TypeError: unsupported operand type(s) for |: 'type' and 'builtin_function_or_method'

A quick reproduction command with Docker:

docker run --rm astral/uv:python3.12-bookworm-slim bash -c 'uvx okama-mcp stdio'

@nervgh
nervgh marked this pull request as ready for review July 26, 2026 14:23
@nervgh
nervgh requested a review from chilango74 July 26, 2026 14:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant