new: add get_security_dividend_details() for announced dividend dates#66
Conversation
Wealthsimple's web app fetches a security's declared dividend schedule via the FetchSecurityDividendDetails query, exposing Security.events with exDividendDate / payableDate / recordDate (plus yield and dividendFrequency). None of the existing queries surface these dates, so consumers had to estimate payment dates from ex-dividend cadences. - Add the FetchSecurityDividendDetails query to GRAPHQL_QUERIES (the web app's own query, verbatim). - Add WealthsimpleAPI.get_security_dividend_details(security_id, currency=None), mirroring get_security_market_data / get_security_historical_quotes. Note: `events` is an empty list until the issuer announces the next dividend.
📝 WalkthroughWalkthroughThis PR adds support for fetching dividend-related security details. A new GraphQL query definition retrieves security data including optional currency-scoped yield fundamentals, dividend-related event dates, and stock dividend frequency. A corresponding public API method constructs GraphQL variables from a security ID and optional currency parameter, executes the query, and returns the security object. ChangesSecurity Dividend Details
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~3 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@ws_api/wealthsimple_api.py`:
- Line 693: The function signature for get_security_dividend_details currently
uses an implicit Optional by declaring currency: str = None; update the
signature to use an explicit Optional type (e.g., currency: str | None = None)
so it satisfies Ruff RUF013; locate the get_security_dividend_details definition
and replace the parameter annotation accordingly (or alternatively import and
use typing.Optional if you prefer) and run linters to confirm the RUF013 warning
is resolved.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: ab9ce190-7b77-470b-9cda-7747d0d87d88
📒 Files selected for processing (2)
ws_api/graphql_queries.pyws_api/wealthsimple_api.py
|
|
||
| return value | ||
|
|
||
| def get_security_dividend_details(self, security_id: str, currency: str = None): |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify implicit-Optional patterns in Python signatures (read-only).
rg -nP --type=py '\bdef\s+\w+\(.*:\s*[^=,\n]+\s*=\s*None'Repository: gboudreau/ws-api-python
Length of output: 462
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Show surrounding code for the flagged method
echo "=== ws_api/wealthsimple_api.py: lines 670-730 ==="
nl -ba ws_api/wealthsimple_api.py | sed -n '670,730p'
# Find Ruff config and whether RUF013 is referenced/enabled
echo
echo "=== Ruff config files ==="
ls -1 pyproject.toml ruff.toml setup.cfg .ruff.toml 2>/dev/null || true
echo
echo "=== Search for RUF013 in repo ==="
rg -n "RUF013" -S .Repository: gboudreau/ws-api-python
Length of output: 178
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== ws_api/wealthsimple_api.py: lines 680-710 (context) ==="
# Use sed (nl isn't available)
sed -n '680,710p' ws_api/wealthsimple_api.py
echo
echo "=== ws_api/wealthsimple_api.py: lines 688-700 (tight) ==="
sed -n '688,700p' ws_api/wealthsimple_api.py
echo
echo "=== Ruff config files (common locations) ==="
ls -1 pyproject.toml ruff.toml setup.cfg .ruff.toml .config/ruff.toml 2>/dev/null || true
echo
echo "=== Search for RUF013 in repo ==="
rg -n "RUF013" -S . || true
echo
echo "=== Search for Ruff 'select'/'ignore' mentioning Optional/implicit ==="
rg -n "ruff|select|ignore|RUF0|implicit|Optional|PEP 484" -S pyproject.toml ruff.toml setup.cfg .ruff.toml 2>/dev/null || trueRepository: gboudreau/ws-api-python
Length of output: 2364
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== ruff.toml (top 120 lines) ==="
sed -n '1,120p' ruff.toml
echo
echo "=== ruff.toml (rest, if any) ==="
sed -n '121,220p' ruff.toml 2>/dev/null || true
echo
echo "=== ruff.toml: look for RUF / implicit / Optional in config ==="
rg -n "select|ignore|RUF|implicit|Optional" ruff.toml
echo
echo "=== ws_api/wealthsimple_api.py: examples of existing '| None' signatures ==="
sed -n '1,80p' ws_api/wealthsimple_api.py
echo
sed -n '430,490p' ws_api/wealthsimple_api.pyRepository: gboudreau/ws-api-python
Length of output: 6136
🏁 Script executed:
#!/bin/bash
# Verify implicit-Optional patterns in Python signatures (read-only).
rg -nP --type=py '\bdef\s+\w+\(.*:\s*[^=,\n]+\s*=\s*None'Repository: gboudreau/ws-api-python
Length of output: 462
🌐 Web query:
Ruff RUF013 implicit Optional str = None
💡 Result:
RUF013 is a lint rule in the Ruff Python linter that detects and flags "implicit Optional" type annotations [1]. What it does: The rule checks for function parameters where the type annotation is specified (e.g., str) but the default value is None, without explicitly marking the type as Optional [1]. PEP 484 prohibits this practice because it is considered ambiguous and inconsistent with the broader type system [1]. Example: Instead of the implicit pattern: def foo(arg: str = None): pass Ruff recommends: from typing import Optional def foo(arg: Optional[str] = None): pass Or, for Python 3.10 and later: def foo(arg: str | None = None): pass Key Details: - Autofix: Ruff provides an automatic fix for this issue [1][2]. If the lint.future-annotations setting is enabled, Ruff may also automatically add from future import annotations to the file, which allows the use of the | operator on Python versions earlier than 3.10 [1][3][4]. - Safety: The autofix is marked as "unsafe" by Ruff because it changes type hints and assumes the provided default value is appropriate, which might not always be the case [1]. - Limitations: The rule does not support type aliases, which may lead to false negatives [1][2]. Additionally, it treats some custom types as Any (which implicitly includes None), meaning those cases may not be flagged [5].
Citations:
- 1: https://docs.astral.sh/ruff/rules/implicit-optional/
- 2: Add rule to disallow implicit optional with autofix astral-sh/ruff#4831
- 3: https://github.com/astral-sh/ruff/blob/0.15.10/changelogs/0.13.x.md
- 4: https://astral.sh/blog/ruff-v0.13.0
- 5: RUF013 undocumented limitation
x: CustomClass = Noneis not caught astral-sh/ruff#14018
🏁 Script executed:
#!/bin/bash
# Verify implicit-Optional patterns in Python signatures (read-only).
rg -nP --type=py '\bdef\s+\w+\(.*:\s*[^=,\n]+\s*=\s*None'Repository: gboudreau/ws-api-python
Length of output: 462
🏁 Script executed:
#!/bin/bash
# Verify implicit-Optional patterns in Python signatures (read-only).
rg -nP --type=py '\bdef\s+\w+\(.*:\s*[^=,\n]+\s*=\s*None'Repository: gboudreau/ws-api-python
Length of output: 462
🏁 Script executed:
#!/bin/bash
# Find function parameters defaulting to None where the type is NOT explicitly Optional (`| None` / `Optional[...]`)
rg -nP --type=py '\bdef\s+\w+\([^)]*\b\w+\s*:\s*(?![^=,\n]*\|\s*None)(?![^=,\n]*\bOptional\[)[^=,\n]+\s*=\s*None'Repository: gboudreau/ws-api-python
Length of output: 183
Use explicit Optional typing for currency (RUF013)
get_security_dividend_details uses currency: str = None, which triggers Ruff’s RUF013 implicit-Optional lint. Change it to currency: str | None = None.
✅ Proposed fix
- def get_security_dividend_details(self, security_id: str, currency: str = None):
+ def get_security_dividend_details(
+ self, security_id: str, currency: str | None = None
+ ):📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| def get_security_dividend_details(self, security_id: str, currency: str = None): | |
| def get_security_dividend_details( | |
| self, security_id: str, currency: str | None = None | |
| ): |
🧰 Tools
🪛 Ruff (0.15.14)
[warning] 693-693: PEP 484 prohibits implicit Optional
Convert to T | None
(RUF013)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@ws_api/wealthsimple_api.py` at line 693, The function signature for
get_security_dividend_details currently uses an implicit Optional by declaring
currency: str = None; update the signature to use an explicit Optional type
(e.g., currency: str | None = None) so it satisfies Ruff RUF013; locate the
get_security_dividend_details definition and replace the parameter annotation
accordingly (or alternatively import and use typing.Optional if you prefer) and
run linters to confirm the RUF013 warning is resolved.
|
Salut Étienne ! :) |
Wealthsimple's web app fetches a security's declared dividend schedule via the FetchSecurityDividendDetails query, exposing Security.events with exDividendDate / payableDate / recordDate (plus yield and dividendFrequency). None of the existing queries surface these dates, so consumers had to estimate payment dates from ex-dividend cadences. - Add the FetchSecurityDividendDetails query to getGraphQLQuery() (the web app's own query, verbatim). - Add WealthsimpleAPI.getSecurityDividendDetails($security_id, $currency). Note: `events` is an empty list until the issuer announces the next dividend. Source: gboudreau/ws-api-python#66
Wealthsimple's web app fetches a security's declared dividend schedule via the FetchSecurityDividendDetails query, exposing Security.events with exDividendDate / payableDate / recordDate (plus yield and dividendFrequency). None of the existing queries surface these dates, so consumers had to estimate payment dates from ex-dividend cadences.
Note:
eventsis an empty list until the issuer announces the next dividend.Summary by CodeRabbit