kensho-kfinance 3.2.7__py3-none-any.whl → 3.2.9__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.

Potentially problematic release.


This version of kensho-kfinance might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kensho-kfinance
3
- Version: 3.2.7
3
+ Version: 3.2.9
4
4
  Summary: Python CLI for kFinance
5
5
  Author-email: Luke Brown <luke.brown@kensho.com>, Michelle Keoy <michelle.keoy@kensho.com>, Keith Page <keith.page@kensho.com>, Matthew Rosen <matthew.rosen@kensho.com>, Nick Roshdieh <nick.roshdieh@kensho.com>
6
6
  Project-URL: source, https://github.com/kensho-technologies/kfinance
@@ -1,11 +1,11 @@
1
- kensho_kfinance-3.2.7.dist-info/licenses/AUTHORS.md,sha256=0h9ClbI0pu1oKj1M28ROUsaxrbZg-6ukQGl6X4y9noI,68
2
- kensho_kfinance-3.2.7.dist-info/licenses/LICENSE,sha256=bsY4blvSgq6o0FMQ3RXa2NCgco--nHCCchLXzxr6kms,83
3
- kfinance/CHANGELOG.md,sha256=UddmW-btMQ2H8aUNxY3gIHVd_Lmr5toYlD-r0L5A-PQ,3054
1
+ kensho_kfinance-3.2.9.dist-info/licenses/AUTHORS.md,sha256=0h9ClbI0pu1oKj1M28ROUsaxrbZg-6ukQGl6X4y9noI,68
2
+ kensho_kfinance-3.2.9.dist-info/licenses/LICENSE,sha256=bsY4blvSgq6o0FMQ3RXa2NCgco--nHCCchLXzxr6kms,83
3
+ kfinance/CHANGELOG.md,sha256=Bmr-5uaCGmPyE6Io5wRAp9XtbTvirW4WEiezpVxBqeA,3331
4
4
  kfinance/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
5
5
  kfinance/conftest.py,sha256=FIZNQyfFbldyVmzaLfWbnMGh6RiC4MZwOVax6815_Ms,3754
6
6
  kfinance/mcp.py,sha256=LTzCIlqsDKRD-0Xcpa_P99-JmJ8duAneO_-GzM43kjw,424
7
7
  kfinance/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- kfinance/version.py,sha256=ADz4iV30MoA4-uH6aIZn2XG9xptnnO-_t_Do6H2M4s0,704
8
+ kfinance/version.py,sha256=d825_zg1e75hjTXcJJrUYWF2PzVuogUemVjSrnFB5a8,704
9
9
  kfinance/client/README.md,sha256=DA5vg4uz1JmJNiqvYywrj46YNhOr584WO8L83Ysx_Mk,372
10
10
  kfinance/client/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  kfinance/client/batch_request_handling.py,sha256=opwJJAU2JtqH-s4vt8wRqhH34MiU4tQP6Ng7K6b3upA,6561
@@ -61,10 +61,10 @@ kfinance/domains/earnings/earning_tools.py,sha256=AmHZQKTGExPPxyDdjhrn5CVLvWr6xM
61
61
  kfinance/domains/earnings/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
62
62
  kfinance/domains/earnings/tests/test_earnings_tools.py,sha256=qGhdWI1s4uEjF6XtFC0f1nlAths1H6xfym-iJyBpwBo,6998
63
63
  kfinance/domains/line_items/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
64
- kfinance/domains/line_items/line_item_models.py,sha256=qDvY2dVGNP9JlujuHYefoi3Q9Yg0ICyEi4HsHx5Cneg,50962
65
- kfinance/domains/line_items/line_item_tools.py,sha256=fLLEGND7S8MLd-0sGKgWUxb3JZP4Rdq4b4azjzlTrZo,4929
64
+ kfinance/domains/line_items/line_item_models.py,sha256=6J_9cko9nZ3OAGSC7OMGEMQW8dkXjRLWn4_2BjtHemU,50969
65
+ kfinance/domains/line_items/line_item_tools.py,sha256=lxvhYbnZKapIf2nIfdtVqXiDswJoeU5XxMOAGUeb8cI,5192
66
66
  kfinance/domains/line_items/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
67
- kfinance/domains/line_items/tests/test_line_item_tools.py,sha256=Bxsf0cGTxbc3dZ6djbC53pA3l0kzogA942LJFNfkuYQ,4082
67
+ kfinance/domains/line_items/tests/test_line_item_tools.py,sha256=vgxJsPbQG1msXZKTfpyHSzUfhw0GvfxZ041T7J-56hU,5499
68
68
  kfinance/domains/mergers_and_acquisitions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
69
69
  kfinance/domains/mergers_and_acquisitions/merger_and_acquisition_models.py,sha256=WAWyBCgYMZj8NLz6nq_sW5MRg_UU5_F9jUUoQ_bcmsM,1893
70
70
  kfinance/domains/mergers_and_acquisitions/merger_and_acquisition_tools.py,sha256=Yx3_TxTWdPcIiOddyAJEddpWc6L-fgx1-JoMtqdPtWQ,7156
@@ -78,14 +78,14 @@ kfinance/domains/prices/tests/test_price_models.py,sha256=PWGqbR9aCys2ldHZMF5anM
78
78
  kfinance/domains/prices/tests/test_price_tools.py,sha256=xNuzAzeu1KuhkB0xF2oIYLVZub9uDg8VLRNmKq-iJ3s,6426
79
79
  kfinance/domains/segments/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
80
80
  kfinance/domains/segments/segment_models.py,sha256=CEZK_B9WM0eppsOpjUbt-ILIcLkQMYgVq4TAx_SrPlc,262
81
- kfinance/domains/segments/segment_tools.py,sha256=DhbTnH6JwRbkJsUqR3bMtzlSNggg9wATRXFo8x4XXho,4330
81
+ kfinance/domains/segments/segment_tools.py,sha256=3zOAn0tayBykTNiprwn32hH-Q0sNJrPwMhnoGSs6yYo,4654
82
82
  kfinance/domains/segments/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
83
- kfinance/domains/segments/tests/test_segment_tools.py,sha256=aOesRHFjR9FG0urmiPCzxYXDNjnrw8sqKovuEnDPHC8,3574
83
+ kfinance/domains/segments/tests/test_segment_tools.py,sha256=Qmh1SpGwVGUhe_r1b4ZpBesu_yN2hq2wiM3z1wmmY6M,4975
84
84
  kfinance/domains/statements/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
85
85
  kfinance/domains/statements/statement_models.py,sha256=f7jEejuvMbsW9paqHIJ19DKUX3XL_qzf74jZBKDamfE,328
86
- kfinance/domains/statements/statement_tools.py,sha256=8zJZtPktbszVuwKifPhY0_k3nsJALyR2SjZoqgEp5gE,4898
86
+ kfinance/domains/statements/statement_tools.py,sha256=RHNQmv4yExXHHxokwgxzLuYG9iCfZuOKRRThm-K3mOQ,5162
87
87
  kfinance/domains/statements/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
88
- kfinance/domains/statements/tests/test_statement_tools.py,sha256=ruojqNUnnBYynJpjl6Oj62c-K2eXV4Gh0whvcgRw3N0,4355
88
+ kfinance/domains/statements/tests/test_statement_tools.py,sha256=mraxvm6tpd-SFRIcco9dKRR2VC8kg1LlYcggBBocLBA,6052
89
89
  kfinance/integrations/README.md,sha256=GalSN11UHzbLfcNzKAlObNbw5XqMKVXSVzzGlryM3zc,320
90
90
  kfinance/integrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
91
91
  kfinance/integrations/local_mcp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -108,7 +108,7 @@ kfinance/integrations/tool_calling/static_tools/tests/test_get_n_quarters_ago.py
108
108
  kfinance/integrations/tool_calling/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
109
109
  kfinance/integrations/tool_calling/tests/test_tool_calling_models.py,sha256=FIusHU4kFmVPuh31Kn57_356tNNVMGTbHApMUFJOaGM,2724
110
110
  kfinance/models/permission_models.py,sha256=G0so8ZOsD1YDsCM4he0z5R9M_shUbSRwD3hUDJdqZl0,635
111
- kensho_kfinance-3.2.7.dist-info/METADATA,sha256=_44qoF4hacG441wRJuZwFy-snXawFUdtnl4zsY1al7A,6197
112
- kensho_kfinance-3.2.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
113
- kensho_kfinance-3.2.7.dist-info/top_level.txt,sha256=kT_kNwVhfQoOAecY8W7uYah5xaHMoHoAdBIvXh6DaKM,9
114
- kensho_kfinance-3.2.7.dist-info/RECORD,,
111
+ kensho_kfinance-3.2.9.dist-info/METADATA,sha256=mKEsNivUKkpEoAL43ulOOgv4tTDLUFOfeYCNak7x3VE,6197
112
+ kensho_kfinance-3.2.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
113
+ kensho_kfinance-3.2.9.dist-info/top_level.txt,sha256=kT_kNwVhfQoOAecY8W7uYah5xaHMoHoAdBIvXh6DaKM,9
114
+ kensho_kfinance-3.2.9.dist-info/RECORD,,
kfinance/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ # v3.2.9
4
+ - Updated tool descriptions for line items, segments, and statements to mention that all period-based inputs and outputs refer only to the calendar year.
5
+
6
+ # v3.2.8
7
+ - Added support for None to LineItemResponse & empty behavior for line items, segments, and statements
8
+
3
9
  # v3.2.7
4
10
  - Fix validator for UnifiedIdTripleResponse
5
11
 
@@ -6,7 +6,7 @@ from pydantic import BaseModel
6
6
 
7
7
 
8
8
  class LineItemResponse(BaseModel):
9
- line_item: dict[str, Decimal]
9
+ line_item: dict[str, Decimal | None]
10
10
 
11
11
 
12
12
  class LineItemType(TypedDict):
@@ -43,6 +43,7 @@ class GetFinancialLineItemFromIdentifiers(KfinanceTool):
43
43
 
44
44
  - When possible, pass multiple identifiers in a single call rather than making multiple calls.
45
45
  - To fetch the most recent value for the line item, leave start_year, start_quarter, end_year, and end_quarter as None.
46
+ - The tool accepts arguments in calendar years, and all outputs will be presented in terms of calendar years. Please note that these calendar years may not align with the company's fiscal year.
46
47
 
47
48
  Example:
48
49
  Query: "What are the revenues of Lowe's and Home Depot?"
@@ -109,9 +110,10 @@ class GetFinancialLineItemFromIdentifiers(KfinanceTool):
109
110
  and len(line_item_responses) > 1
110
111
  ):
111
112
  for line_item_response in line_item_responses.values():
112
- most_recent_year = max(line_item_response.line_item.keys())
113
- most_recent_year_data = line_item_response.line_item[most_recent_year]
114
- line_item_response.line_item = {most_recent_year: most_recent_year_data}
113
+ if line_item_response.line_item:
114
+ most_recent_year = max(line_item_response.line_item.keys())
115
+ most_recent_year_data = line_item_response.line_item[most_recent_year]
116
+ line_item_response.line_item = {most_recent_year: most_recent_year_data}
115
117
 
116
118
  return GetFinancialLineItemFromIdentifiersResp(
117
119
  results=line_item_responses, errors=list(id_triple_resp.errors.values())
@@ -86,6 +86,38 @@ class TestGetFinancialLineItemFromCompanyIds:
86
86
  response = tool.run(args.model_dump(mode="json"))
87
87
  assert response == expected_response
88
88
 
89
+ def test_empty_most_recent_request(self, requests_mock: Mocker, mock_client: Client) -> None:
90
+ """
91
+ GIVEN the GetFinancialLineItemFromIdentifiers tool
92
+ WHEN we request most recent line items for multiple companies
93
+ THEN we only get back the most recent line item for each company
94
+ UNLESS no line items exist
95
+ """
96
+
97
+ company_ids = [1, 2]
98
+
99
+ c_1_line_item_resp = LineItemResponse(line_item={})
100
+ c_2_line_item_resp = LineItemResponse(line_item={"2024": Decimal(14208000000)})
101
+ expected_response = GetFinancialLineItemFromIdentifiersResp(
102
+ results={"C_1": c_1_line_item_resp, "C_2": c_2_line_item_resp},
103
+ )
104
+
105
+ requests_mock.get(
106
+ url=f"https://kfinance.kensho.com/api/v1/line_item/1/revenue/none/none/none/none/none",
107
+ json={"line_item": {}},
108
+ )
109
+ requests_mock.get(
110
+ url=f"https://kfinance.kensho.com/api/v1/line_item/2/revenue/none/none/none/none/none",
111
+ json=self.line_item_resp,
112
+ )
113
+ tool = GetFinancialLineItemFromIdentifiers(kfinance_client=mock_client)
114
+ args = GetFinancialLineItemFromIdentifiersArgs(
115
+ identifiers=[f"{COMPANY_ID_PREFIX}{company_id}" for company_id in company_ids],
116
+ line_item="revenue",
117
+ )
118
+ response = tool.run(args.model_dump(mode="json"))
119
+ assert response == expected_response
120
+
89
121
  def test_line_items_and_aliases_included_in_schema(self, mock_client: Client):
90
122
  """
91
123
  GIVEN a GetFinancialLineItemFromCompanyIds tool
@@ -1,3 +1,4 @@
1
+ from textwrap import dedent
1
2
  from typing import Literal, Type
2
3
 
3
4
  from pydantic import BaseModel, Field
@@ -30,7 +31,11 @@ class GetSegmentsFromIdentifiersResp(ToolRespWithErrors):
30
31
 
31
32
  class GetSegmentsFromIdentifiers(KfinanceTool):
32
33
  name: str = "get_segments_from_identifiers"
33
- description: str = "Get the templated segments associated with a list of identifiers."
34
+ description: str = dedent("""
35
+ Get the templated segments associated with a list of identifiers.
36
+
37
+ - The tool accepts arguments in calendar years, and all outputs will be presented in terms of calendar years. Please note that these calendar years may not align with the company's fiscal year.
38
+ """).strip()
34
39
  args_schema: Type[BaseModel] = GetSegmentsFromIdentifiersArgs
35
40
  accepted_permissions: set[Permission] | None = {Permission.SegmentsPermission}
36
41
 
@@ -98,9 +103,10 @@ class GetSegmentsFromIdentifiers(KfinanceTool):
98
103
  and len(segments_responses) > 1
99
104
  ):
100
105
  for segments_response in segments_responses.values():
101
- most_recent_year = max(segments_response.segments.keys())
102
- most_recent_year_data = segments_response.segments[most_recent_year]
103
- segments_response.segments = {most_recent_year: most_recent_year_data}
106
+ if segments_response.segments:
107
+ most_recent_year = max(segments_response.segments.keys())
108
+ most_recent_year_data = segments_response.segments[most_recent_year]
109
+ segments_response.segments = {most_recent_year: most_recent_year_data}
104
110
 
105
111
  return GetSegmentsFromIdentifiersResp(
106
112
  results=segments_responses, errors=list(id_triple_resp.errors.values())
@@ -63,8 +63,8 @@ class TestGetSegmentsFromIdentifier:
63
63
  def test_most_recent_request(self, requests_mock: Mocker, mock_client: Client) -> None:
64
64
  """
65
65
  GIVEN the GetFinancialLineItemFromIdentifiers tool
66
- WHEN we request most recent statement for multiple companies
67
- THEN we only get back the most recent statement for each company
66
+ WHEN we request most recent segment for multiple companies
67
+ THEN we only get back the most recent segment for each company
68
68
  """
69
69
 
70
70
  company_ids = [1, 2]
@@ -90,3 +90,38 @@ class TestGetSegmentsFromIdentifier:
90
90
  )
91
91
  response = tool.run(args.model_dump(mode="json"))
92
92
  assert response == expected_response
93
+
94
+ def test_empty_most_recent_request(self, requests_mock: Mocker, mock_client: Client) -> None:
95
+ """
96
+ GIVEN the GetFinancialLineItemFromIdentifiers tool
97
+ WHEN we request most recent segment for multiple companies
98
+ THEN we only get back the most recent segment for each company
99
+ UNLESS no segments exist
100
+ """
101
+
102
+ company_ids = [1, 2]
103
+ expected_response = GetSegmentsFromIdentifiersResp.model_validate(
104
+ {
105
+ "results": {
106
+ "C_1": {"segments": {}},
107
+ "C_2": {"segments": {"2021": self.segments_response["segments"]["2021"]}},
108
+ }
109
+ }
110
+ )
111
+
112
+ requests_mock.get(
113
+ url=f"https://kfinance.kensho.com/api/v1/segments/1/business/none/none/none/none/none",
114
+ json={"segments": {}},
115
+ )
116
+ requests_mock.get(
117
+ url=f"https://kfinance.kensho.com/api/v1/segments/2/business/none/none/none/none/none",
118
+ json=self.segments_response,
119
+ )
120
+
121
+ tool = GetSegmentsFromIdentifiers(kfinance_client=mock_client)
122
+ args = GetSegmentsFromIdentifiersArgs(
123
+ identifiers=[f"{COMPANY_ID_PREFIX}{company_id}" for company_id in company_ids],
124
+ segment_type=SegmentType.business,
125
+ )
126
+ response = tool.run(args.model_dump(mode="json"))
127
+ assert response == expected_response
@@ -35,6 +35,7 @@ class GetFinancialStatementFromIdentifiers(KfinanceTool):
35
35
  Get a financial statement associated with a group of identifiers.
36
36
 
37
37
  - To fetch the most recent value for the statement, leave start_year, start_quarter, end_year, and end_quarter as None.
38
+ - The tool accepts arguments in calendar years, and all outputs will be presented in terms of calendar years. Please note that these calendar years may not align with the company's fiscal year.
38
39
 
39
40
  Example:
40
41
  Query: "Fetch the balance sheets of BAC and GS for 2024"
@@ -105,9 +106,10 @@ class GetFinancialStatementFromIdentifiers(KfinanceTool):
105
106
  and len(statement_responses) > 1
106
107
  ):
107
108
  for statement_response in statement_responses.values():
108
- most_recent_year = max(statement_response.statements.keys())
109
- most_recent_year_data = statement_response.statements[most_recent_year]
110
- statement_response.statements = {most_recent_year: most_recent_year_data}
109
+ if statement_response.statements:
110
+ most_recent_year = max(statement_response.statements.keys())
111
+ most_recent_year_data = statement_response.statements[most_recent_year]
112
+ statement_response.statements = {most_recent_year: most_recent_year_data}
111
113
 
112
114
  return GetFinancialStatementFromIdentifiersResp(
113
115
  results=statement_responses, errors=list(id_triple_resp.errors.values())
@@ -105,3 +105,45 @@ class TestGetFinancialStatementFromIdentifiers:
105
105
  )
106
106
  response = tool.run(args.model_dump(mode="json"))
107
107
  assert response == expected_response
108
+
109
+ def test_empty_most_recent_request(self, requests_mock: Mocker, mock_client: Client) -> None:
110
+ """
111
+ GIVEN the GetFinancialStatementFromIdentifiers tool
112
+ WHEN we request most recent statement for multiple companies
113
+ THEN we only get back the most recent statement for each company
114
+ UNLESS no statements exist
115
+ """
116
+
117
+ company_ids = [1, 2]
118
+ expected_response = GetFinancialStatementFromIdentifiersResp.model_validate(
119
+ {
120
+ "results": {
121
+ "C_1": {"statements": {}},
122
+ "C_2": {
123
+ "statements": {
124
+ "2021": {
125
+ "Revenues": "8243000000.000000",
126
+ "Total Revenues": "8243000000.000000",
127
+ }
128
+ }
129
+ },
130
+ }
131
+ }
132
+ )
133
+
134
+ requests_mock.get(
135
+ url=f"https://kfinance.kensho.com/api/v1/statements/1/income_statement/none/none/none/none/none",
136
+ json={"statements": {}},
137
+ )
138
+ requests_mock.get(
139
+ url=f"https://kfinance.kensho.com/api/v1/statements/2/income_statement/none/none/none/none/none",
140
+ json=self.statement_resp,
141
+ )
142
+
143
+ tool = GetFinancialStatementFromIdentifiers(kfinance_client=mock_client)
144
+ args = GetFinancialStatementFromIdentifiersArgs(
145
+ identifiers=[f"{COMPANY_ID_PREFIX}{company_id}" for company_id in company_ids],
146
+ statement=StatementType.income_statement,
147
+ )
148
+ response = tool.run(args.model_dump(mode="json"))
149
+ assert response == expected_response
kfinance/version.py CHANGED
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '3.2.7'
32
- __version_tuple__ = version_tuple = (3, 2, 7)
31
+ __version__ = version = '3.2.9'
32
+ __version_tuple__ = version_tuple = (3, 2, 9)
33
33
 
34
34
  __commit_id__ = commit_id = None