kensho-kfinance 3.2.4__py3-none-any.whl → 4.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. {kensho_kfinance-3.2.4.dist-info → kensho_kfinance-4.0.0.dist-info}/METADATA +3 -3
  2. {kensho_kfinance-3.2.4.dist-info → kensho_kfinance-4.0.0.dist-info}/RECORD +57 -56
  3. kfinance/CHANGELOG.md +51 -0
  4. kfinance/client/batch_request_handling.py +3 -1
  5. kfinance/client/fetch.py +127 -54
  6. kfinance/client/kfinance.py +38 -39
  7. kfinance/client/meta_classes.py +50 -20
  8. kfinance/client/models/date_and_period_models.py +32 -7
  9. kfinance/client/models/decimal_with_unit.py +14 -2
  10. kfinance/client/models/response_models.py +33 -0
  11. kfinance/client/models/tests/test_decimal_with_unit.py +9 -0
  12. kfinance/client/tests/test_batch_requests.py +5 -4
  13. kfinance/client/tests/test_fetch.py +134 -58
  14. kfinance/client/tests/test_objects.py +207 -145
  15. kfinance/conftest.py +10 -0
  16. kfinance/domains/business_relationships/business_relationship_tools.py +17 -8
  17. kfinance/domains/business_relationships/tests/test_business_relationship_tools.py +18 -16
  18. kfinance/domains/capitalizations/capitalization_models.py +7 -5
  19. kfinance/domains/capitalizations/capitalization_tools.py +38 -20
  20. kfinance/domains/capitalizations/tests/test_capitalization_tools.py +66 -36
  21. kfinance/domains/companies/company_models.py +22 -2
  22. kfinance/domains/companies/company_tools.py +49 -16
  23. kfinance/domains/companies/tests/test_company_tools.py +27 -9
  24. kfinance/domains/competitors/competitor_tools.py +19 -5
  25. kfinance/domains/competitors/tests/test_competitor_tools.py +22 -19
  26. kfinance/domains/cusip_and_isin/cusip_and_isin_tools.py +29 -8
  27. kfinance/domains/cusip_and_isin/tests/test_cusip_and_isin_tools.py +13 -8
  28. kfinance/domains/earnings/earning_tools.py +73 -29
  29. kfinance/domains/earnings/tests/test_earnings_tools.py +52 -43
  30. kfinance/domains/line_items/line_item_models.py +372 -16
  31. kfinance/domains/line_items/line_item_tools.py +198 -46
  32. kfinance/domains/line_items/tests/test_line_item_tools.py +305 -39
  33. kfinance/domains/mergers_and_acquisitions/merger_and_acquisition_models.py +46 -2
  34. kfinance/domains/mergers_and_acquisitions/merger_and_acquisition_tools.py +55 -74
  35. kfinance/domains/mergers_and_acquisitions/tests/test_merger_and_acquisition_tools.py +61 -59
  36. kfinance/domains/prices/price_models.py +7 -6
  37. kfinance/domains/prices/price_tools.py +24 -16
  38. kfinance/domains/prices/tests/test_price_tools.py +47 -39
  39. kfinance/domains/segments/segment_models.py +17 -3
  40. kfinance/domains/segments/segment_tools.py +102 -42
  41. kfinance/domains/segments/tests/test_segment_tools.py +166 -37
  42. kfinance/domains/statements/statement_models.py +17 -3
  43. kfinance/domains/statements/statement_tools.py +130 -46
  44. kfinance/domains/statements/tests/test_statement_tools.py +251 -49
  45. kfinance/integrations/local_mcp/kfinance_mcp.py +1 -1
  46. kfinance/integrations/tests/test_example_notebook.py +57 -16
  47. kfinance/integrations/tool_calling/all_tools.py +5 -1
  48. kfinance/integrations/tool_calling/static_tools/get_n_quarters_ago.py +5 -0
  49. kfinance/integrations/tool_calling/static_tools/tests/test_get_lastest.py +13 -10
  50. kfinance/integrations/tool_calling/static_tools/tests/test_get_n_quarters_ago.py +2 -1
  51. kfinance/integrations/tool_calling/tests/test_tool_calling_models.py +15 -4
  52. kfinance/integrations/tool_calling/tool_calling_models.py +18 -6
  53. kfinance/version.py +2 -2
  54. {kensho_kfinance-3.2.4.dist-info → kensho_kfinance-4.0.0.dist-info}/WHEEL +0 -0
  55. {kensho_kfinance-3.2.4.dist-info → kensho_kfinance-4.0.0.dist-info}/licenses/AUTHORS.md +0 -0
  56. {kensho_kfinance-3.2.4.dist-info → kensho_kfinance-4.0.0.dist-info}/licenses/LICENSE +0 -0
  57. {kensho_kfinance-3.2.4.dist-info → kensho_kfinance-4.0.0.dist-info}/top_level.txt +0 -0
@@ -18,6 +18,7 @@ from kfinance.domains.companies.company_models import (
18
18
  CompanyIdAndName,
19
19
  CompanyOtherNames,
20
20
  )
21
+ from kfinance.domains.segments.segment_models import SegmentType
21
22
 
22
23
 
23
24
  def build_mock_api_client() -> KFinanceApiClient:
@@ -95,59 +96,107 @@ class TestFetchItem(TestCase):
95
96
  def test_fetch_statement(self) -> None:
96
97
  company_id = 21719
97
98
  statement_type = "BS"
98
- expected_fetch_url = f"{self.kfinance_api_client.url_base}statements/{company_id}/{statement_type}/none/none/none/none/none"
99
- # Validation error is ok, we only care that the function was called with the correct url
100
- with pytest.raises(ValidationError):
101
- self.kfinance_api_client.fetch_statement(
102
- company_id=company_id, statement_type=statement_type
103
- )
104
- self.kfinance_api_client.fetch.assert_called_with(expected_fetch_url)
99
+ expected_url = f"{self.kfinance_api_client.url_base}statements/"
100
+ expected_request_body = {
101
+ "company_ids": [company_id],
102
+ "statement_type": statement_type,
103
+ }
104
+ # Mock the response to have the expected PostResponse structure
105
+ self.kfinance_api_client.fetch.return_value = {"results": {}, "errors": {}}
106
+ result = self.kfinance_api_client.fetch_statement(
107
+ company_ids=[company_id], statement_type=statement_type
108
+ )
109
+ self.kfinance_api_client.fetch.assert_called_with(
110
+ expected_url, method="POST", request_body=expected_request_body
111
+ )
112
+ # Verify the result is a PostResponse
113
+ assert "results" in result.model_dump()
114
+ # errors field is excluded when empty
115
+
105
116
  period_type = PeriodType.quarterly
106
117
  start_year = 2024
107
118
  end_year = 2024
108
119
  start_quarter = 1
109
120
  end_quarter = 4
110
- expected_fetch_url = f"{self.kfinance_api_client.url_base}statements/{company_id}/{statement_type}/{period_type.value}/{start_year}/{end_year}/{start_quarter}/{end_quarter}"
111
- # Validation error is ok, we only care that the function was called with the correct url
112
- with pytest.raises(ValidationError):
113
- self.kfinance_api_client.fetch_statement(
114
- company_id=company_id,
115
- statement_type=statement_type,
116
- period_type=period_type,
117
- start_year=start_year,
118
- end_year=end_year,
119
- start_quarter=start_quarter,
120
- end_quarter=end_quarter,
121
- )
122
- self.kfinance_api_client.fetch.assert_called_with(expected_fetch_url)
121
+ expected_request_body = {
122
+ "company_ids": [company_id],
123
+ "statement_type": statement_type,
124
+ "period_type": period_type.value,
125
+ "start_year": start_year,
126
+ "end_year": end_year,
127
+ "start_quarter": start_quarter,
128
+ "end_quarter": end_quarter,
129
+ }
130
+ # Mock the response to have the expected PostResponse structure
131
+ self.kfinance_api_client.fetch.return_value = {"results": {}, "errors": {}}
132
+ result = self.kfinance_api_client.fetch_statement(
133
+ company_ids=[company_id],
134
+ statement_type=statement_type,
135
+ period_type=period_type,
136
+ start_year=start_year,
137
+ end_year=end_year,
138
+ start_quarter=start_quarter,
139
+ end_quarter=end_quarter,
140
+ )
141
+ self.kfinance_api_client.fetch.assert_called_with(
142
+ expected_url, method="POST", request_body=expected_request_body
143
+ )
144
+ # Verify the result is a PostResponse
145
+ assert "results" in result.model_dump()
146
+ # errors field is excluded when empty
123
147
 
124
148
  def test_fetch_line_item(self) -> None:
125
149
  company_id = 21719
126
150
  line_item = "cash"
127
- expected_fetch_url = f"{self.kfinance_api_client.url_base}line_item/{company_id}/{line_item}/none/none/none/none/none"
128
- # Validation error is ok, we only care that the function was called with the correct url
129
- with pytest.raises(ValidationError):
130
- self.kfinance_api_client.fetch_line_item(company_id=company_id, line_item=line_item)
131
- self.kfinance_api_client.fetch.assert_called_with(expected_fetch_url)
151
+ expected_url = f"{self.kfinance_api_client.url_base}line_item/"
152
+ expected_request_body = {
153
+ "company_ids": [company_id],
154
+ "line_item": line_item,
155
+ }
156
+ # Mock the response to have the expected PostResponse structure
157
+ self.kfinance_api_client.fetch.return_value = {"results": {}, "errors": {}}
158
+ result = self.kfinance_api_client.fetch_line_item(
159
+ company_ids=[company_id], line_item=line_item
160
+ )
161
+ self.kfinance_api_client.fetch.assert_called_with(
162
+ expected_url, method="POST", request_body=expected_request_body
163
+ )
164
+ # Verify the result is a PostResponse
165
+ assert "results" in result.model_dump()
166
+ # errors field is excluded when empty
167
+
132
168
  period_type = PeriodType.quarterly
133
169
  start_year = 2024
134
170
  end_year = 2024
135
171
  start_quarter = 1
136
172
  end_quarter = 4
137
- expected_fetch_url = f"{self.kfinance_api_client.url_base}line_item/{company_id}/{line_item}/{period_type.value}/{start_year}/{end_year}/{start_quarter}/{end_quarter}"
173
+ expected_request_body = {
174
+ "company_ids": [company_id],
175
+ "line_item": line_item,
176
+ "period_type": period_type.value,
177
+ "start_year": start_year,
178
+ "end_year": end_year,
179
+ "start_quarter": start_quarter,
180
+ "end_quarter": end_quarter,
181
+ }
138
182
 
139
- # Validation error is ok, we only care that the function was called with the correct url
140
- with pytest.raises(ValidationError):
141
- self.kfinance_api_client.fetch_line_item(
142
- company_id=company_id,
143
- line_item=line_item,
144
- period_type=period_type,
145
- start_year=start_year,
146
- end_year=end_year,
147
- start_quarter=start_quarter,
148
- end_quarter=end_quarter,
149
- )
150
- self.kfinance_api_client.fetch.assert_called_with(expected_fetch_url)
183
+ # Mock the response to have the expected PostResponse structure
184
+ self.kfinance_api_client.fetch.return_value = {"results": {}, "errors": {}}
185
+ result = self.kfinance_api_client.fetch_line_item(
186
+ company_ids=[company_id],
187
+ line_item=line_item,
188
+ period_type=period_type,
189
+ start_year=start_year,
190
+ end_year=end_year,
191
+ start_quarter=start_quarter,
192
+ end_quarter=end_quarter,
193
+ )
194
+ self.kfinance_api_client.fetch.assert_called_with(
195
+ expected_url, method="POST", request_body=expected_request_body
196
+ )
197
+ # Verify the result is a PostResponse
198
+ assert "results" in result.model_dump()
199
+ # errors field is excluded when empty
151
200
 
152
201
  def test_fetch_info(self) -> None:
153
202
  company_id = 21719
@@ -275,30 +324,55 @@ class TestFetchItem(TestCase):
275
324
 
276
325
  def test_fetch_segments(self) -> None:
277
326
  company_id = 21719
278
- segment_type = "business"
279
- expected_fetch_url = f"{self.kfinance_api_client.url_base}segments/{company_id}/{segment_type}/none/none/none/none/none"
280
- with pytest.raises(ValidationError):
281
- self.kfinance_api_client.fetch_segments(
282
- company_id=company_id, segment_type=segment_type
283
- )
284
- self.kfinance_api_client.fetch.assert_called_with(expected_fetch_url)
327
+ segment_type = SegmentType.business
328
+ expected_url = f"{self.kfinance_api_client.url_base}segments/"
329
+ expected_request_body = {
330
+ "company_ids": [company_id],
331
+ "segment_type": segment_type.value,
332
+ }
333
+ # Mock the response to have the expected PostResponse structure
334
+ self.kfinance_api_client.fetch.return_value = {"results": {}, "errors": {}}
335
+ result = self.kfinance_api_client.fetch_segments(
336
+ company_ids=[company_id], segment_type=segment_type
337
+ )
338
+ self.kfinance_api_client.fetch.assert_called_with(
339
+ expected_url, method="POST", request_body=expected_request_body
340
+ )
341
+ # Verify the result is a PostResponse
342
+ assert "results" in result.model_dump()
343
+ # errors field is excluded when empty
344
+
285
345
  period_type = PeriodType.quarterly
286
346
  start_year = 2023
287
347
  end_year = 2023
288
348
  start_quarter = 1
289
349
  end_quarter = 4
290
- expected_fetch_url = f"{self.kfinance_api_client.url_base}segments/{company_id}/{segment_type}/{period_type.value}/{start_year}/{end_year}/{start_quarter}/{end_quarter}"
291
- with pytest.raises(ValidationError):
292
- self.kfinance_api_client.fetch_segments(
293
- company_id=company_id,
294
- segment_type=segment_type,
295
- period_type=period_type,
296
- start_year=start_year,
297
- end_year=end_year,
298
- start_quarter=start_quarter,
299
- end_quarter=end_quarter,
300
- )
301
- self.kfinance_api_client.fetch.assert_called_with(expected_fetch_url)
350
+ expected_request_body = {
351
+ "company_ids": [company_id],
352
+ "segment_type": segment_type.value,
353
+ "period_type": period_type.value,
354
+ "start_year": start_year,
355
+ "end_year": end_year,
356
+ "start_quarter": start_quarter,
357
+ "end_quarter": end_quarter,
358
+ }
359
+ # Mock the response to have the expected PostResponse structure
360
+ self.kfinance_api_client.fetch.return_value = {"results": {}, "errors": {}}
361
+ result = self.kfinance_api_client.fetch_segments(
362
+ company_ids=[company_id],
363
+ segment_type=segment_type,
364
+ period_type=period_type,
365
+ start_year=start_year,
366
+ end_year=end_year,
367
+ start_quarter=start_quarter,
368
+ end_quarter=end_quarter,
369
+ )
370
+ self.kfinance_api_client.fetch.assert_called_with(
371
+ expected_url, method="POST", request_body=expected_request_body
372
+ )
373
+ # Verify the result is a PostResponse
374
+ assert "results" in result.model_dump()
375
+ # errors field is excluded when empty
302
376
 
303
377
  def test_fetch_mergers_for_company(self) -> None:
304
378
  company_id = 21719
@@ -311,7 +385,9 @@ class TestFetchItem(TestCase):
311
385
  def test_fetch_merger_info(self) -> None:
312
386
  transaction_id = 554979212
313
387
  expected_fetch_url = f"{self.kfinance_api_client.url_base}merger/info/{transaction_id}"
314
- self.kfinance_api_client.fetch_merger_info(transaction_id=transaction_id)
388
+ # Validation error is ok, we only care that the function was called with the correct url
389
+ with pytest.raises(ValidationError):
390
+ self.kfinance_api_client.fetch_merger_info(transaction_id=transaction_id)
315
391
  self.kfinance_api_client.fetch.assert_called_with(expected_fetch_url)
316
392
 
317
393
  def test_fetch_advisors_for_company_in_merger(self) -> None: