Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 38 additions & 36 deletions crates/fmp-py/python/fmp/_native/congressional/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ class CongressionalDebtDetails:
__match_args__: tuple[typing.Literal["date_incurred"]]

@property
def date_incurred(self) -> builtins.str: ...
def date_incurred(self) -> typing.Optional[builtins.str]: ...
def __eq__(self, other: builtins.object, /) -> builtins.bool: ...
def __new__(cls, *, date_incurred: builtins.str) -> CongressionalDebtDetails: ...
def __new__(
cls, *, date_incurred: typing.Optional[builtins.str]
) -> CongressionalDebtDetails: ...
def __getnewargs_ex__(self) -> tuple[tuple, dict]: ...
def __repr__(self) -> builtins.str: ...
def to_dict(self) -> builtins.dict[builtins.str, typing.Any]:
Expand Down Expand Up @@ -68,23 +70,23 @@ class CongressionalMemberNetWorth:
@property
def section(self) -> builtins.str: ...
@property
def category(self) -> builtins.str: ...
def category(self) -> typing.Optional[builtins.str]: ...
@property
def name(self) -> builtins.str: ...
def name(self) -> typing.Optional[builtins.str]: ...
@property
def asset_type(self) -> builtins.str: ...
@property
def income_type(self) -> typing.Optional[builtins.str]: ...
@property
def owner(self) -> builtins.str: ...
def owner(self) -> typing.Optional[builtins.str]: ...
@property
def comment(self) -> typing.Optional[builtins.str]: ...
@property
def debt_details(self) -> typing.Optional[CongressionalDebtDetails]: ...
@property
def value_range(self) -> typing.Optional[CongressionalNetWorthRange]: ...
@property
def value(self) -> builtins.int: ...
def value(self) -> typing.Optional[builtins.float]: ...
@property
def income_range(self) -> typing.Optional[CongressionalNetWorthRange]: ...
@property
Expand All @@ -100,15 +102,15 @@ class CongressionalMemberNetWorth:
year: builtins.int,
filing_date: datetime.date,
section: builtins.str,
category: builtins.str,
name: builtins.str,
category: typing.Optional[builtins.str],
name: typing.Optional[builtins.str],
asset_type: builtins.str,
income_type: typing.Optional[builtins.str],
owner: builtins.str,
owner: typing.Optional[builtins.str],
comment: typing.Optional[builtins.str],
debt_details: typing.Optional[CongressionalDebtDetails],
value_range: typing.Optional[CongressionalNetWorthRange],
value: builtins.int,
value: typing.Optional[builtins.float],
income_range: typing.Optional[CongressionalNetWorthRange],
income: typing.Optional[builtins.str],
link: builtins.str,
Expand Down Expand Up @@ -147,47 +149,47 @@ class CongressionalMemberNetWorthAggregate:
@property
def year(self) -> builtins.int: ...
@property
def total(self) -> builtins.int: ...
def total(self) -> builtins.float: ...
@property
def real_estate_liabilities(self) -> builtins.int: ...
def real_estate_liabilities(self) -> typing.Optional[builtins.float]: ...
@property
def cash_and_cash_equivalents(self) -> builtins.int: ...
def cash_and_cash_equivalents(self) -> builtins.float: ...
@property
def business_and_self_employment(self) -> builtins.int: ...
def business_and_self_employment(self) -> typing.Optional[builtins.float]: ...
@property
def real_estate(self) -> builtins.int: ...
def real_estate(self) -> typing.Optional[builtins.float]: ...
@property
def ownership_interest(self) -> builtins.int: ...
def ownership_interest(self) -> typing.Optional[builtins.float]: ...
@property
def stock(self) -> builtins.int: ...
def stock(self) -> typing.Optional[builtins.float]: ...
@property
def options(self) -> builtins.int: ...
def options(self) -> typing.Optional[builtins.float]: ...
@property
def revolving_and_credit_lines(self) -> builtins.int: ...
def revolving_and_credit_lines(self) -> typing.Optional[builtins.float]: ...
@property
def asset_backed_securities(self) -> builtins.int: ...
def asset_backed_securities(self) -> typing.Optional[builtins.float]: ...
@property
def business_liabilities(self) -> builtins.int: ...
def business_liabilities(self) -> typing.Optional[builtins.float]: ...
@property
def mutual_funds_and_etfs(self) -> builtins.int: ...
def mutual_funds_and_etfs(self) -> builtins.float: ...
def __eq__(self, other: builtins.object, /) -> builtins.bool: ...
def __new__(
cls,
*,
member_id: builtins.str,
year: builtins.int,
total: builtins.int,
real_estate_liabilities: builtins.int,
cash_and_cash_equivalents: builtins.int,
business_and_self_employment: builtins.int,
real_estate: builtins.int,
ownership_interest: builtins.int,
stock: builtins.int,
options: builtins.int,
revolving_and_credit_lines: builtins.int,
asset_backed_securities: builtins.int,
business_liabilities: builtins.int,
mutual_funds_and_etfs: builtins.int,
total: builtins.float,
real_estate_liabilities: typing.Optional[builtins.float],
cash_and_cash_equivalents: builtins.float,
business_and_self_employment: typing.Optional[builtins.float],
real_estate: typing.Optional[builtins.float],
ownership_interest: typing.Optional[builtins.float],
stock: typing.Optional[builtins.float],
options: typing.Optional[builtins.float],
revolving_and_credit_lines: typing.Optional[builtins.float],
asset_backed_securities: typing.Optional[builtins.float],
business_liabilities: typing.Optional[builtins.float],
mutual_funds_and_etfs: builtins.float,
) -> CongressionalMemberNetWorthAggregate: ...
def __getnewargs_ex__(self) -> tuple[tuple, dict]: ...
def __repr__(self) -> builtins.str: ...
Expand Down Expand Up @@ -451,10 +453,10 @@ class CongressionalNetWorthRange:
@property
def min(self) -> builtins.int: ...
@property
def max(self) -> builtins.int: ...
def max(self) -> typing.Optional[builtins.int]: ...
def __eq__(self, other: builtins.object, /) -> builtins.bool: ...
def __new__(
cls, *, min: builtins.int, max: builtins.int
cls, *, min: builtins.int, max: typing.Optional[builtins.int]
) -> CongressionalNetWorthRange: ...
def __getnewargs_ex__(self) -> tuple[tuple, dict]: ...
def __repr__(self) -> builtins.str: ...
Expand Down
74 changes: 37 additions & 37 deletions crates/fmp-py/src/models/congressional.rs
Original file line number Diff line number Diff line change
Expand Up @@ -715,7 +715,7 @@ pub(crate) struct CongressionalNetWorthRange {
#[pyo3(get)]
pub min: i64,
#[pyo3(get)]
pub max: i64,
pub max: Option<i64>,
}

#[gen_stub_pymethods]
Expand All @@ -725,7 +725,7 @@ impl CongressionalNetWorthRange {
#[allow(clippy::too_many_arguments)]
#[allow(clippy::fn_params_excessive_bools)]
#[pyo3(signature = (*, min, max))]
fn new(min: i64, max: i64) -> Self {
fn new(min: i64, max: Option<i64>) -> Self {
Self { min, max }
}

Expand Down Expand Up @@ -798,7 +798,7 @@ impl crate::models::convert::DictValue for CongressionalNetWorthRange {
#[derive(Clone, PartialEq)]
pub(crate) struct CongressionalDebtDetails {
#[pyo3(get)]
pub date_incurred: String,
pub date_incurred: Option<String>,
}

#[gen_stub_pymethods]
Expand All @@ -808,7 +808,7 @@ impl CongressionalDebtDetails {
#[allow(clippy::too_many_arguments)]
#[allow(clippy::fn_params_excessive_bools)]
#[pyo3(signature = (*, date_incurred))]
fn new(date_incurred: String) -> Self {
fn new(date_incurred: Option<String>) -> Self {
Self { date_incurred }
}

Expand Down Expand Up @@ -860,7 +860,7 @@ impl CongressionalDebtDetails {
impl From<libfmp::responses::congressional::CongressionalDebtDetails> for CongressionalDebtDetails {
fn from(value: libfmp::responses::congressional::CongressionalDebtDetails) -> Self {
Self {
date_incurred: value.date_incurred.0,
date_incurred: value.date_incurred.map(|value| value.0),
}
}
}
Expand All @@ -886,23 +886,23 @@ pub(crate) struct CongressionalMemberNetWorth {
#[pyo3(get)]
pub section: String,
#[pyo3(get)]
pub category: String,
pub category: Option<String>,
#[pyo3(get)]
pub name: String,
pub name: Option<String>,
#[pyo3(get)]
pub asset_type: String,
#[pyo3(get)]
pub income_type: Option<String>,
#[pyo3(get)]
pub owner: String,
pub owner: Option<String>,
#[pyo3(get)]
pub comment: Option<String>,
#[pyo3(get)]
pub debt_details: Option<crate::models::congressional::CongressionalDebtDetails>,
#[pyo3(get)]
pub value_range: Option<crate::models::congressional::CongressionalNetWorthRange>,
#[pyo3(get)]
pub value: i64,
pub value: Option<f64>,
#[pyo3(get)]
pub income_range: Option<crate::models::congressional::CongressionalNetWorthRange>,
income: Option<::serde_json::Value>,
Expand All @@ -923,15 +923,15 @@ impl CongressionalMemberNetWorth {
year: u32,
filing_date: ::chrono::NaiveDate,
section: String,
category: String,
name: String,
category: Option<String>,
name: Option<String>,
asset_type: String,
income_type: Option<String>,
owner: String,
owner: Option<String>,
comment: Option<String>,
debt_details: Option<crate::models::congressional::CongressionalDebtDetails>,
value_range: Option<crate::models::congressional::CongressionalNetWorthRange>,
value: i64,
value: Option<f64>,
income_range: Option<crate::models::congressional::CongressionalNetWorthRange>,
income: Option<String>,
link: String,
Expand Down Expand Up @@ -1219,29 +1219,29 @@ pub(crate) struct CongressionalMemberNetWorthAggregate {
#[pyo3(get)]
pub year: u32,
#[pyo3(get)]
pub total: i64,
pub total: f64,
#[pyo3(get)]
pub real_estate_liabilities: i64,
pub real_estate_liabilities: Option<f64>,
#[pyo3(get)]
pub cash_and_cash_equivalents: i64,
pub cash_and_cash_equivalents: f64,
#[pyo3(get)]
pub business_and_self_employment: i64,
pub business_and_self_employment: Option<f64>,
#[pyo3(get)]
pub real_estate: i64,
pub real_estate: Option<f64>,
#[pyo3(get)]
pub ownership_interest: i64,
pub ownership_interest: Option<f64>,
#[pyo3(get)]
pub stock: i64,
pub stock: Option<f64>,
#[pyo3(get)]
pub options: i64,
pub options: Option<f64>,
#[pyo3(get)]
pub revolving_and_credit_lines: i64,
pub revolving_and_credit_lines: Option<f64>,
#[pyo3(get)]
pub asset_backed_securities: i64,
pub asset_backed_securities: Option<f64>,
#[pyo3(get)]
pub business_liabilities: i64,
pub business_liabilities: Option<f64>,
#[pyo3(get)]
pub mutual_funds_and_etfs: i64,
pub mutual_funds_and_etfs: f64,
}

#[gen_stub_pymethods]
Expand All @@ -1254,18 +1254,18 @@ impl CongressionalMemberNetWorthAggregate {
fn new(
member_id: String,
year: u32,
total: i64,
real_estate_liabilities: i64,
cash_and_cash_equivalents: i64,
business_and_self_employment: i64,
real_estate: i64,
ownership_interest: i64,
stock: i64,
options: i64,
revolving_and_credit_lines: i64,
asset_backed_securities: i64,
business_liabilities: i64,
mutual_funds_and_etfs: i64,
total: f64,
real_estate_liabilities: Option<f64>,
cash_and_cash_equivalents: f64,
business_and_self_employment: Option<f64>,
real_estate: Option<f64>,
ownership_interest: Option<f64>,
stock: Option<f64>,
options: Option<f64>,
revolving_and_credit_lines: Option<f64>,
asset_backed_securities: Option<f64>,
business_liabilities: Option<f64>,
mutual_funds_and_etfs: f64,
) -> Self {
Self {
member_id,
Expand Down
56 changes: 56 additions & 0 deletions crates/fmp-py/tests/test_congressional_b.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,3 +285,59 @@ def test_profiles_decode_null_image_to_none(client: Any, fixture_server: Fixture
rows = client.congressional.profiles()

assert rows[0].image is None


def test_net_worth_decodes_fractional_value_and_null_members(client: Any, fixture_server: FixtureServer) -> None:
"""A fractional ``value`` decodes exactly; null itemized members and a null range ``max`` decode to ``None``."""
body = load_fixture("congress_senate_net_worth.json")
body[0]["value"] = 32500.5
del body[0]["debtDetails"]["dateIncurred"]
fractional = dict(body[0], category=None, name=None, owner=None, value=None, valueRange={"min": 1, "max": None})
fixture_server.route("/senate-net-worth", [body[0], fractional])
rows = client.congressional.net_worth(MEMBER_ID)

assert rows[0].value == 32500.5
assert rows[0].debt_details.date_incurred is None
assert rows[1].category is None
assert rows[1].name is None
assert rows[1].owner is None
assert rows[1].value is None
assert rows[1].value_range.max is None


def test_net_worth_aggregated_decodes_fractional_amounts_and_absent_members(
client: Any, fixture_server: FixtureServer
) -> None:
"""Fractional amounts decode exactly and absent aggregate members decode to ``None``."""
body = load_fixture("congress_senate_net_worth_aggregated.json")
for member in (
"realEstateLiabilities",
"businessAndSelfEmployment",
"ownershipInterest",
"options",
"revolvingAndCreditLines",
"assetBackedSecurities",
"businessLiabilities",
):
del body[0][member]
body[0].update(total=59082540.5, cashAndCashEquivalents=121004.5, realEstate=3000000.5, stock=8000.5)
body[0]["mutualFundsAndETFs"] = 34526531.5
sparse = {key: value for key, value in body[0].items() if key not in ("realEstate", "stock")}
fixture_server.route("/senate-net-worth-aggregated", [body[0], sparse])
rows = client.congressional.net_worth_aggregated(MEMBER_ID)
row = rows[0]

assert row.total == 59082540.5
assert row.cash_and_cash_equivalents == 121004.5
assert row.real_estate == 3000000.5
assert row.stock == 8000.5
assert row.mutual_funds_and_etfs == 34526531.5
assert row.real_estate_liabilities is None
assert row.business_and_self_employment is None
assert row.ownership_interest is None
assert row.options is None
assert row.revolving_and_credit_lines is None
assert row.asset_backed_securities is None
assert row.business_liabilities is None
assert rows[1].real_estate is None
assert rows[1].stock is None
6 changes: 4 additions & 2 deletions crates/fmp-py/tests/typecheck_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,10 @@ def check_congressional_contract(client: FmpClient) -> None:
totals: list[CongressionalMemberNetWorthAggregate] = client.congressional.net_worth_aggregated(
"P000197", totals_col="stock"
)
total: int = totals[0].total
_ = (disclosed, gains, born, years_active, value_range, total)
value: float | None = entries[0].value
total: float = totals[0].total
options: float | None = totals[0].options
_ = (disclosed, gains, born, years_active, value_range, value, total, options)


def check_funds_contract(client: FmpClient) -> None:
Expand Down
Loading
Loading