Skip to content

Add get_dividends function and fix ISSClient query parameter merging#2

Open
ncaraw04-cell wants to merge 2 commits intombk-dev:masterfrom
ncaraw04-cell:feature/dividends
Open

Add get_dividends function and fix ISSClient query parameter merging#2
ncaraw04-cell wants to merge 2 commits intombk-dev:masterfrom
ncaraw04-cell:feature/dividends

Conversation

@ncaraw04-cell
Copy link

@ncaraw04-cell ncaraw04-cell commented Mar 14, 2026

  • Added get_dividends function to fetch historical dividend data.
  • Fixed a bug in ISSClient._make_query that caused a TypeError when overlapping query parameters were used (like iss.meta).
  • Added a basic unit test in tests/test_requests.py.

Summary by Sourcery

Add a new helper to fetch MOEX dividend history and expose it in the public API while fixing query parameter merging in the ISS client.

New Features:

  • Introduce get_dividends request function to retrieve historical dividend data for a specific security from the MOEX ISS API.

Bug Fixes:

  • Fix ISSClient._make_query to merge base and user-provided query parameters without raising errors when keys overlap.

Enhancements:

  • Explicitly define the public API in moex.init via all to include ISSClient and all request helper functions, including get_dividends.

Tests:

  • Add a unit test covering get_dividends to ensure it returns non-empty dividend data for a sample security.

@sourcery-ai
Copy link

sourcery-ai bot commented Mar 14, 2026

Reviewer's Guide

Adds a new get_dividends helper for fetching dividend history via ISSClient, exports it from the package, and fixes ISSClient query parameter merging to avoid TypeError when overlapping parameters like iss.meta are used, along with a basic regression test.

Sequence diagram for get_dividends using ISSClient with fixed query merging

sequenceDiagram
    actor Caller
    participant RequestsModule
    participant ISSClient
    participant ISSClient_make_query as ISSClient_make_query
    participant HTTPClient

    Caller->>RequestsModule: get_dividends(session, security, kwargs)
    RequestsModule->>RequestsModule: build url for security
    RequestsModule->>RequestsModule: query = {iss.meta: off}
    RequestsModule->>RequestsModule: query.update(kwargs)
    RequestsModule->>ISSClient: create ISSClient(session, url, query)
    RequestsModule->>ISSClient: get(start)
    ISSClient->>ISSClient_make_query: _make_query(start)
    ISSClient_make_query->>ISSClient_make_query: query = BASE_QUERY.copy()
    ISSClient_make_query->>ISSClient_make_query: query.update(self._query)
    ISSClient_make_query-->>ISSClient: merged query
    ISSClient->>HTTPClient: HTTP GET url with merged query
    HTTPClient-->>ISSClient: JSON response
    ISSClient-->>RequestsModule: res dict
    RequestsModule->>RequestsModule: dividends = res.get(dividends, [])
    RequestsModule-->>Caller: dividends list
Loading

Class diagram for ISSClient and new get_dividends helper

classDiagram
    class ISSClient {
        - session : requests.Session
        - url : str
        - query : Dict~str, Any~
        + get(start : int) Dict~str, Any~
        - _make_query(start : int) Dict~str, Union~str, int~
    }

    class RequestsModule {
        + get_dividends(session : requests.Session, security : str, kwargs : Any) List~Dict~str, Any~~
    }

    class BASE_QUERY {
        <<dict>>
    }

    RequestsModule ..> ISSClient : creates
    ISSClient ..> BASE_QUERY : uses in _make_query

    %% get_dividends logic
    %% RequestsModule : query = {iss.meta: off}
    %% RequestsModule : query.update(kwargs)
    %% RequestsModule : iss = ISSClient(session, url, query)
    %% RequestsModule : res = iss.get()
    %% RequestsModule : return res.get(dividends, [])
Loading

File-Level Changes

Change Details Files
Introduce get_dividends helper to fetch dividend history for a given security via MOEX ISS API.
  • Add get_dividends to the public requests API list so it can be imported from moex.requests
  • Implement get_dividends to build the dividends endpoint URL, default iss.meta=off in the query, merge in extra kwargs, call ISSClient.get, and return the dividends table or an empty list
  • Document parameters, return type, and link to ISS reference 140 in the get_dividends docstring
moex/requests.py
Make get_dividends available at the top-level moex package and define an explicit public API list.
  • Replace wildcard export behavior with an explicit all list including ISSClient and all request functions, including get_dividends
  • Ensure the library’s public surface is well-defined and stable for consumers relying on from moex import * or direct attribute access
moex/__init__.py
Fix ISSClient query merging to avoid TypeError when overlapping keys exist between BASE_QUERY and user query parameters.
  • Change _make_query to start from a shallow copy of BASE_QUERY and then update with self._query instead of using dict(**BASE_QUERY, **self._query)
  • Preserve ability to optionally add the start parameter without mutating BASE_QUERY
moex/client.py
Add a regression/unit test for get_dividends behavior.
  • Create test_get_dividends that calls requests.get_dividends for ticker SBER against the test session fixture
  • Assert that the result is a non-empty list of dicts with correct secid and the presence of the value field
tests/test_requests.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue, and left some high level feedback:

  • For consistency with the other request helpers, consider reusing existing internal helpers (like _get_short_data) in get_dividends instead of manually constructing and calling ISSClient directly.
  • In get_dividends, the explicit query = {"iss.meta": "off"} followed by query.update(kwargs) allows callers to override iss.meta; if the intent is to always suppress metadata, you may want to prevent kwargs from overriding that key.
  • The explicit __all__ list in moex/__init__.py now duplicates the public surface of requests; this will require manual updates for every new helper, so consider deriving this from requests or limiting __all__ maintenance to a single place.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- For consistency with the other request helpers, consider reusing existing internal helpers (like `_get_short_data`) in `get_dividends` instead of manually constructing and calling `ISSClient` directly.
- In `get_dividends`, the explicit `query = {"iss.meta": "off"}` followed by `query.update(kwargs)` allows callers to override `iss.meta`; if the intent is to always suppress metadata, you may want to prevent kwargs from overriding that key.
- The explicit `__all__` list in `moex/__init__.py` now duplicates the public surface of `requests`; this will require manual updates for every new helper, so consider deriving this from `requests` or limiting `__all__` maintenance to a single place.

## Individual Comments

### Comment 1
<location path="tests/test_requests.py" line_range="297-302" />
<code_context>
     assert data[25]['till'] == '2023-03-03'
-    assert data[35]['tradingsession'] == 3
+
+def test_get_dividends(session):
+    data = requests.get_dividends(session, "SBER")
+    assert isinstance(data, list)
+    assert len(data) > 0
+    assert data[0]["secid"] == "SBER"
+    assert "value" in data[0]
</code_context>
<issue_to_address>
**suggestion (testing):** Extend `test_get_dividends` to cover edge cases such as empty results and custom query parameters.

The current test only covers the happy path for a known security. Please also add cases for:

- A security with no dividend history (should return an empty list without raising).
- Passing extra query parameters via `**kwargs` (e.g., date filters) to ensure they’re forwarded and handled.
- Overriding `iss.meta` via `**kwargs` to confirm user-supplied values are respected.

These will better exercise the query-building logic and robustness of `get_dividends`.

Suggested implementation:

```python
def test_get_dividends(session):
    # Happy path for a known security
    data = requests.get_dividends(session, "SBER")
    assert isinstance(data, list)
    assert len(data) > 0
    assert data[0]["secid"] == "SBER"
    assert "value" in data[0]

    # Edge case: a date range with no expected dividends should return an empty list
    empty_data = requests.get_dividends(
        session,
        "SBER",
        from_="2100-01-01",
        till="2100-12-31",
    )
    assert isinstance(empty_data, list)
    assert len(empty_data) == 0

    # Edge case: extra query parameters via **kwargs (e.g., limit)
    limited_data = requests.get_dividends(session, "SBER", limit=1)
    assert isinstance(limited_data, list)
    assert 0 <= len(limited_data) <= 1

    # Edge case: overriding iss.meta via **kwargs
    no_meta_data = requests.get_dividends(session, "SBER", iss_meta="off")
    assert isinstance(no_meta_data, list)
    assert len(no_meta_data) > 0
    assert no_meta_data[0]["secid"] == "SBER"

```

If `get_dividends` does not currently support `from_`, `till`, `limit`, or `iss_meta` as keyword arguments, you will need to:
1. Update its signature to accept `**kwargs`.
2. Ensure those `**kwargs` are forwarded into the underlying request/query-building logic (e.g., included in the params dict when calling the ISS API).
3. If the API expects `from` instead of `from_`, map `from_` to `"from"` inside `get_dividends`.
Adjust the parameter names in the test to match the actual supported query parameters in your codebase.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +297 to +302
def test_get_dividends(session):
data = requests.get_dividends(session, "SBER")
assert isinstance(data, list)
assert len(data) > 0
assert data[0]["secid"] == "SBER"
assert "value" in data[0]
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (testing): Extend test_get_dividends to cover edge cases such as empty results and custom query parameters.

The current test only covers the happy path for a known security. Please also add cases for:

  • A security with no dividend history (should return an empty list without raising).
  • Passing extra query parameters via **kwargs (e.g., date filters) to ensure they’re forwarded and handled.
  • Overriding iss.meta via **kwargs to confirm user-supplied values are respected.

These will better exercise the query-building logic and robustness of get_dividends.

Suggested implementation:

def test_get_dividends(session):
    # Happy path for a known security
    data = requests.get_dividends(session, "SBER")
    assert isinstance(data, list)
    assert len(data) > 0
    assert data[0]["secid"] == "SBER"
    assert "value" in data[0]

    # Edge case: a date range with no expected dividends should return an empty list
    empty_data = requests.get_dividends(
        session,
        "SBER",
        from_="2100-01-01",
        till="2100-12-31",
    )
    assert isinstance(empty_data, list)
    assert len(empty_data) == 0

    # Edge case: extra query parameters via **kwargs (e.g., limit)
    limited_data = requests.get_dividends(session, "SBER", limit=1)
    assert isinstance(limited_data, list)
    assert 0 <= len(limited_data) <= 1

    # Edge case: overriding iss.meta via **kwargs
    no_meta_data = requests.get_dividends(session, "SBER", iss_meta="off")
    assert isinstance(no_meta_data, list)
    assert len(no_meta_data) > 0
    assert no_meta_data[0]["secid"] == "SBER"

If get_dividends does not currently support from_, till, limit, or iss_meta as keyword arguments, you will need to:

  1. Update its signature to accept **kwargs.
  2. Ensure those **kwargs are forwarded into the underlying request/query-building logic (e.g., included in the params dict when calling the ISS API).
  3. If the API expects from instead of from_, map from_ to "from" inside get_dividends.
    Adjust the parameter names in the test to match the actual supported query parameters in your codebase.

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