financechatbotkit 2.0.0__tar.gz → 3.1.0__tar.gz

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 (84) hide show
  1. financechatbotkit-3.1.0/PKG-INFO +228 -0
  2. financechatbotkit-3.1.0/README.md +204 -0
  3. {financechatbotkit-2.0.0 → financechatbotkit-3.1.0}/pyproject.toml +25 -5
  4. financechatbotkit-3.1.0/src/financechatbotkit/__init__.py +0 -0
  5. financechatbotkit-3.1.0/src/financechatbotkit/orchestrator/__init__.py +90 -0
  6. financechatbotkit-3.1.0/src/financechatbotkit/orchestrator/dart/__init__.py +21 -0
  7. financechatbotkit-3.1.0/src/financechatbotkit/orchestrator/dart/api_client.py +66 -0
  8. financechatbotkit-3.1.0/src/financechatbotkit/orchestrator/dart/tree_to_outline.py +287 -0
  9. financechatbotkit-3.1.0/src/financechatbotkit/orchestrator/dart/xml_to_dict.py +116 -0
  10. financechatbotkit-3.1.0/src/financechatbotkit/orchestrator/dart/xml_to_tree.py +360 -0
  11. financechatbotkit-3.1.0/src/financechatbotkit/orchestrator/dart/zip_extractor.py +46 -0
  12. financechatbotkit-3.1.0/src/financechatbotkit/orchestrator/exceptions.py +25 -0
  13. financechatbotkit-3.1.0/src/financechatbotkit/orchestrator/kind/__init__.py +41 -0
  14. financechatbotkit-3.1.0/src/financechatbotkit/orchestrator/kind/download.py +282 -0
  15. financechatbotkit-3.1.0/src/financechatbotkit/orchestrator/kind/parser.py +236 -0
  16. financechatbotkit-3.1.0/src/financechatbotkit/orchestrator/kind/query.py +375 -0
  17. financechatbotkit-3.1.0/src/financechatbotkit/orchestrator/kind/workflow.py +352 -0
  18. {financechatbotkit-2.0.0/src → financechatbotkit-3.1.0/src/financechatbotkit}/orchestrator/price/workflow.py +59 -12
  19. financechatbotkit-3.1.0/src/financechatbotkit/orchestrator/storage.py +77 -0
  20. financechatbotkit-3.1.0/src/financechatbotkit/telebotkit/__init__.py +75 -0
  21. {financechatbotkit-2.0.0/src → financechatbotkit-3.1.0/src/financechatbotkit}/telebotkit/bot/__init__.py +5 -5
  22. {financechatbotkit-2.0.0/src → financechatbotkit-3.1.0/src/financechatbotkit}/telebotkit/bot/client.py +1 -1
  23. {financechatbotkit-2.0.0/src → financechatbotkit-3.1.0/src/financechatbotkit}/telebotkit/firestore/__init__.py +5 -5
  24. {financechatbotkit-2.0.0/src → financechatbotkit-3.1.0/src/financechatbotkit}/telebotkit/firestore/documents.py +2 -2
  25. {financechatbotkit-2.0.0/src → financechatbotkit-3.1.0/src/financechatbotkit}/telebotkit/firestore/fetch.py +1 -1
  26. {financechatbotkit-2.0.0/src → financechatbotkit-3.1.0/src/financechatbotkit}/telebotkit/firestore/locks.py +1 -1
  27. {financechatbotkit-2.0.0/src → financechatbotkit-3.1.0/src/financechatbotkit}/telebotkit/firestore/upload.py +2 -2
  28. financechatbotkit-3.1.0/src/financechatbotkit/utilitykit/__init__.py +52 -0
  29. financechatbotkit-3.1.0/src/financechatbotkit/utilitykit/excel/__init__.py +20 -0
  30. financechatbotkit-3.1.0/src/financechatbotkit/utilitykit/excel/table_builders.py +117 -0
  31. financechatbotkit-3.1.0/src/financechatbotkit/utilitykit/excel/types.py +10 -0
  32. financechatbotkit-3.1.0/src/financechatbotkit/utilitykit/excel/value_utils.py +74 -0
  33. financechatbotkit-3.1.0/src/financechatbotkit/utilitykit/excel/xlsx_reader.py +38 -0
  34. financechatbotkit-3.1.0/src/financechatbotkit/utilitykit/excel/xlsx_writer.py +175 -0
  35. financechatbotkit-3.1.0/src/financechatbotkit.egg-info/PKG-INFO +228 -0
  36. financechatbotkit-3.1.0/src/financechatbotkit.egg-info/SOURCES.txt +72 -0
  37. financechatbotkit-3.1.0/src/financechatbotkit.egg-info/entry_points.txt +2 -0
  38. financechatbotkit-3.1.0/src/financechatbotkit.egg-info/requires.txt +22 -0
  39. financechatbotkit-3.1.0/src/financechatbotkit.egg-info/top_level.txt +1 -0
  40. {financechatbotkit-2.0.0 → financechatbotkit-3.1.0}/tests/test_bond_workflow.py +2 -2
  41. financechatbotkit-3.1.0/tests/test_dart_archive.py +29 -0
  42. financechatbotkit-3.1.0/tests/test_dart_xml_json.py +29 -0
  43. {financechatbotkit-2.0.0 → financechatbotkit-3.1.0}/tests/test_fnguide_workflow.py +9 -9
  44. financechatbotkit-3.1.0/tests/test_kind_download.py +379 -0
  45. financechatbotkit-3.1.0/tests/test_kind_json_conversion.py +114 -0
  46. {financechatbotkit-2.0.0 → financechatbotkit-3.1.0}/tests/test_price_workflow.py +123 -10
  47. {financechatbotkit-2.0.0 → financechatbotkit-3.1.0}/tests/test_update_raw_data.py +1 -1
  48. financechatbotkit-3.1.0/tests/test_utilitykit_excel.py +192 -0
  49. {financechatbotkit-2.0.0 → financechatbotkit-3.1.0}/tests/test_workflow.py +3 -3
  50. financechatbotkit-2.0.0/PKG-INFO +0 -11
  51. financechatbotkit-2.0.0/README.md +0 -52
  52. financechatbotkit-2.0.0/src/financechatbotkit.egg-info/PKG-INFO +0 -11
  53. financechatbotkit-2.0.0/src/financechatbotkit.egg-info/SOURCES.txt +0 -47
  54. financechatbotkit-2.0.0/src/financechatbotkit.egg-info/entry_points.txt +0 -2
  55. financechatbotkit-2.0.0/src/financechatbotkit.egg-info/requires.txt +0 -6
  56. financechatbotkit-2.0.0/src/financechatbotkit.egg-info/top_level.txt +0 -2
  57. financechatbotkit-2.0.0/src/orchestrator/__init__.py +0 -29
  58. financechatbotkit-2.0.0/src/orchestrator/exceptions.py +0 -17
  59. financechatbotkit-2.0.0/src/telebotkit/__init__.py +0 -51
  60. {financechatbotkit-2.0.0 → financechatbotkit-3.1.0}/setup.cfg +0 -0
  61. {financechatbotkit-2.0.0/src → financechatbotkit-3.1.0/src/financechatbotkit}/orchestrator/bond/__init__.py +0 -0
  62. {financechatbotkit-2.0.0/src → financechatbotkit-3.1.0/src/financechatbotkit}/orchestrator/bond/base_reader.py +0 -0
  63. {financechatbotkit-2.0.0/src → financechatbotkit-3.1.0/src/financechatbotkit}/orchestrator/bond/getBondBasiInfo.py +0 -0
  64. {financechatbotkit-2.0.0/src → financechatbotkit-3.1.0/src/financechatbotkit}/orchestrator/bond/getBondWithOptiCallRede.py +0 -0
  65. {financechatbotkit-2.0.0/src → financechatbotkit-3.1.0/src/financechatbotkit}/orchestrator/bond/getEarlExerOpti.py +0 -0
  66. {financechatbotkit-2.0.0/src → financechatbotkit-3.1.0/src/financechatbotkit}/orchestrator/bond/getIssuIssuItemStat.py +0 -0
  67. {financechatbotkit-2.0.0/src → financechatbotkit-3.1.0/src/financechatbotkit}/orchestrator/bond/getOptiExer.py +0 -0
  68. {financechatbotkit-2.0.0/src → financechatbotkit-3.1.0/src/financechatbotkit}/orchestrator/bond/getOptiExerPricAdju.py +0 -0
  69. {financechatbotkit-2.0.0/src → financechatbotkit-3.1.0/src/financechatbotkit}/orchestrator/bond/workflow.py +0 -0
  70. {financechatbotkit-2.0.0/src → financechatbotkit-3.1.0/src/financechatbotkit}/orchestrator/fnguide/__init__.py +0 -0
  71. {financechatbotkit-2.0.0/src → financechatbotkit-3.1.0/src/financechatbotkit}/orchestrator/fnguide/workflow.py +0 -0
  72. {financechatbotkit-2.0.0/src → financechatbotkit-3.1.0/src/financechatbotkit}/orchestrator/mapping/__init__.py +0 -0
  73. {financechatbotkit-2.0.0/src → financechatbotkit-3.1.0/src/financechatbotkit}/orchestrator/mapping/data/__init__.py +0 -0
  74. {financechatbotkit-2.0.0/src → financechatbotkit-3.1.0/src/financechatbotkit}/orchestrator/mapping/data/corp_codes_raw.json +0 -0
  75. {financechatbotkit-2.0.0/src → financechatbotkit-3.1.0/src/financechatbotkit}/orchestrator/mapping/update_raw_data.py +0 -0
  76. {financechatbotkit-2.0.0/src → financechatbotkit-3.1.0/src/financechatbotkit}/orchestrator/mapping/workflow.py +0 -0
  77. {financechatbotkit-2.0.0/src → financechatbotkit-3.1.0/src/financechatbotkit}/orchestrator/price/__init__.py +0 -0
  78. {financechatbotkit-2.0.0/src → financechatbotkit-3.1.0/src/financechatbotkit}/telebotkit/bot/reply.py +0 -0
  79. {financechatbotkit-2.0.0/src → financechatbotkit-3.1.0/src/financechatbotkit}/telebotkit/bot/router.py +0 -0
  80. {financechatbotkit-2.0.0/src → financechatbotkit-3.1.0/src/financechatbotkit}/telebotkit/bot/safety.py +0 -0
  81. {financechatbotkit-2.0.0/src → financechatbotkit-3.1.0/src/financechatbotkit}/telebotkit/bot/telegram.py +0 -0
  82. {financechatbotkit-2.0.0/src → financechatbotkit-3.1.0/src/financechatbotkit}/telebotkit/firestore/client.py +0 -0
  83. {financechatbotkit-2.0.0/src → financechatbotkit-3.1.0/src/financechatbotkit}/telebotkit/sheets.py +0 -0
  84. {financechatbotkit-2.0.0 → financechatbotkit-3.1.0}/src/financechatbotkit.egg-info/dependency_links.txt +0 -0
@@ -0,0 +1,228 @@
1
+ Metadata-Version: 2.4
2
+ Name: financechatbotkit
3
+ Version: 3.1.0
4
+ Summary: FinanceChatbot workflows (orchestrator) and Telegram/Firestore helpers (TeleBotKit)
5
+ Requires-Python: >=3.11
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: httpx<1,>=0.27
8
+ Requires-Dist: python-dotenv<2,>=1
9
+ Provides-Extra: orchestrator
10
+ Requires-Dist: beautifulsoup4<5,>=4.12; extra == "orchestrator"
11
+ Requires-Dist: finance-datareader==0.9.110; extra == "orchestrator"
12
+ Requires-Dist: lxml>=5; extra == "orchestrator"
13
+ Provides-Extra: firestore
14
+ Requires-Dist: google-cloud-firestore>=2.16.0; extra == "firestore"
15
+ Requires-Dist: google-api-core>=2.15.0; extra == "firestore"
16
+ Requires-Dist: google-auth>=2.28.0; extra == "firestore"
17
+ Provides-Extra: excel
18
+ Requires-Dist: openpyxl>=3.1.0; extra == "excel"
19
+ Provides-Extra: all
20
+ Requires-Dist: financechatbotkit[excel,firestore,orchestrator]; extra == "all"
21
+ Provides-Extra: dev
22
+ Requires-Dist: pytest>=8; extra == "dev"
23
+ Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
24
+
25
+ ## FinanceChatbot
26
+
27
+ `FinanceChatbot` bundles three installable code areas under `src/`:
28
+
29
+ - `orchestrator`: finance data workflows
30
+ - `utilitykit`: reusable utility helpers
31
+ - `telebotkit`: Telegram / Firestore helpers
32
+
33
+ The package name is `financechatbotkit`, and it currently requires Python 3.11+.
34
+
35
+ ## Orchestrator
36
+
37
+ `orchestrator` is the main workflow library for:
38
+
39
+ - `mapping`
40
+ - `price`
41
+ - `fnguide`
42
+ - `bond`
43
+ - `kind`
44
+
45
+ ### Public API
46
+
47
+ ```python
48
+ from orchestrator import (
49
+ FnGuideWorkflow,
50
+ KindWorkflow,
51
+ MappingWorkflow,
52
+ MarketBondWorkflow,
53
+ PricePeriodWorkflow,
54
+ )
55
+ ```
56
+
57
+ Feature-level imports are also available:
58
+
59
+ ```python
60
+ from orchestrator.mapping import MappingWorkflow
61
+ from orchestrator.price import PricePeriodWorkflow
62
+ from orchestrator.fnguide import FnGuideWorkflow
63
+ from orchestrator.bond import MarketBondWorkflow
64
+ from orchestrator.kind import KindWorkflow, parse_kind_html_to_json
65
+ ```
66
+
67
+ Most workflow classes return a normalized payload shaped like:
68
+
69
+ ```python
70
+ {
71
+ "input": {...},
72
+ "data": {...},
73
+ }
74
+ ```
75
+
76
+ `price` workflows support `price_fields="close"` (default), `price_fields="oclh"`, `price_fields="oclhv"`, `price_fields="oclhva"`, and comma-separated field lists such as `price_fields="volume,amount"` to control which price columns are returned. `PricePeriodWorkflow` also supports `price_source="krx"` when KRX `Amount` data is required for VWAP.
77
+
78
+ ### Workflow Classes
79
+
80
+ The main usage pattern is class-based:
81
+
82
+ - `MappingWorkflow`
83
+ - `PricePeriodWorkflow`
84
+ - `PriceSnapshotWorkflow`
85
+ - `FnGuideWorkflow`
86
+ - `MarketBondWorkflow`
87
+ - `KindWorkflow`
88
+
89
+ For example, `FnGuideWorkflow` is used like this:
90
+
91
+ ```python
92
+ from orchestrator.fnguide import FnGuideWorkflow
93
+
94
+ workflow = FnGuideWorkflow()
95
+ result = workflow.run(stock_code="005930", statement_type="consolidated")
96
+ ```
97
+
98
+ ### KIND Workflow
99
+
100
+ `kind` is slightly different from the other workflow modules because it supports both:
101
+
102
+ - request payload construction and raw response download
103
+ - HTML file parsing into structured JSON
104
+
105
+ The recommended entry point is `KindWorkflow`.
106
+
107
+ ```python
108
+ from pathlib import Path
109
+
110
+ from orchestrator.kind import KindWorkflow
111
+ from run import KIND_REQUEST_HEADERS
112
+
113
+ workflow = KindWorkflow()
114
+ result = workflow.run(
115
+ output_directory=Path("resources/kind_2012"),
116
+ request_headers=KIND_REQUEST_HEADERS,
117
+ start_date="2012-01-01",
118
+ end_date="2012-12-31",
119
+ start_page=1,
120
+ end_page=10,
121
+ disclosure_type_groups={"01": ["0119"]},
122
+ last_report_only=True,
123
+ save=True,
124
+ )
125
+
126
+ print(result["input_snapshot_path"])
127
+ print(result["checkpoint_path"])
128
+ ```
129
+
130
+ `KindWorkflow` stores normalized input state and, when `save=True`, writes:
131
+
132
+ - raw `.body` files page by page
133
+ - `kind_workflow.input.json`
134
+ - `kind_workflow.checkpoint.json`
135
+
136
+ This makes long-running downloads easier to inspect and recover.
137
+
138
+ Lower-level helpers remain available when needed:
139
+
140
+ ```python
141
+ from orchestrator.kind import (
142
+ build_kind_search_request_data,
143
+ parse_kind_file_to_json,
144
+ parse_kind_html_to_json,
145
+ save_kind_search_results,
146
+ )
147
+ ```
148
+
149
+ ### Example Script
150
+
151
+ `run.py` shows one concrete KIND pipeline:
152
+
153
+ 1. Download paged KIND responses through `KindWorkflow`
154
+ 2. Merge downloaded `.body` files into a single JSON file
155
+ 3. Convert the merged JSON into Excel using `utilitykit`
156
+
157
+ ## UtilityKit
158
+
159
+ `utilitykit` is a shared utilities package for repo-wide helpers that do not belong to `orchestrator`.
160
+
161
+ Current public utilities:
162
+
163
+ - `utilitykit.excel.read_xlsx_sheet_as_json()`
164
+ - `utilitykit.excel.write_json_to_xlsx()`
165
+ - `utilitykit.excel.records_to_table()`
166
+ - `utilitykit.excel.project_records_to_table()`
167
+ - `utilitykit.excel.row_cell_records_to_table()`
168
+
169
+ ### Excel Examples
170
+
171
+ Read an Excel sheet as `list[list]` using A1-start automatic bounds detection:
172
+
173
+ ```python
174
+ from utilitykit import read_xlsx_sheet_as_json
175
+
176
+ table = read_xlsx_sheet_as_json("sample.xlsx", sheet_name="Data")
177
+ ```
178
+
179
+ Write row-oriented data:
180
+
181
+ ```python
182
+ from utilitykit import write_json_to_xlsx
183
+
184
+ write_json_to_xlsx(
185
+ [
186
+ {"company": "Samsung", "sales": 100},
187
+ {"company": "LG", "sales": 80},
188
+ ],
189
+ "rows.xlsx",
190
+ sheet_name="Rows",
191
+ axis="rows",
192
+ item_mode="dict",
193
+ )
194
+ ```
195
+
196
+ Write column-oriented data:
197
+
198
+ ```python
199
+ from utilitykit import write_json_to_xlsx
200
+
201
+ write_json_to_xlsx(
202
+ {"company": ["Samsung", "LG"], "sales": [100, 80]},
203
+ "columns.xlsx",
204
+ sheet_name="Columns",
205
+ axis="columns",
206
+ item_mode="dict",
207
+ )
208
+ ```
209
+
210
+ ## TeleBotKit
211
+
212
+ `TeleBotKit` is a shared helper package that lives under `src/telebotkit` and is packaged together with this project.
213
+
214
+ It provides helpers for:
215
+
216
+ - Telegram bot command parsing, routing, MarkdownV2 escaping, and reply payload generation (`telebotkit.bot`)
217
+ - Firestore client bootstrap, typed repositories, shared document access, and lease/lock helpers (`telebotkit.firestore`)
218
+ - Excel row parsing and typed JSON payload generation for Firestore imports (`telebotkit.sheets`)
219
+
220
+ ### Example Usage
221
+
222
+ ```python
223
+ from telebotkit.bot import Reply, Router
224
+ from telebotkit.firestore import DocumentStore, get_client
225
+ from telebotkit.sheets import build_typed_rows_payload_from_xlsx
226
+ ```
227
+
228
+ See `src/telebotkit/README.md` for fuller API documentation and examples.
@@ -0,0 +1,204 @@
1
+ ## FinanceChatbot
2
+
3
+ `FinanceChatbot` bundles three installable code areas under `src/`:
4
+
5
+ - `orchestrator`: finance data workflows
6
+ - `utilitykit`: reusable utility helpers
7
+ - `telebotkit`: Telegram / Firestore helpers
8
+
9
+ The package name is `financechatbotkit`, and it currently requires Python 3.11+.
10
+
11
+ ## Orchestrator
12
+
13
+ `orchestrator` is the main workflow library for:
14
+
15
+ - `mapping`
16
+ - `price`
17
+ - `fnguide`
18
+ - `bond`
19
+ - `kind`
20
+
21
+ ### Public API
22
+
23
+ ```python
24
+ from orchestrator import (
25
+ FnGuideWorkflow,
26
+ KindWorkflow,
27
+ MappingWorkflow,
28
+ MarketBondWorkflow,
29
+ PricePeriodWorkflow,
30
+ )
31
+ ```
32
+
33
+ Feature-level imports are also available:
34
+
35
+ ```python
36
+ from orchestrator.mapping import MappingWorkflow
37
+ from orchestrator.price import PricePeriodWorkflow
38
+ from orchestrator.fnguide import FnGuideWorkflow
39
+ from orchestrator.bond import MarketBondWorkflow
40
+ from orchestrator.kind import KindWorkflow, parse_kind_html_to_json
41
+ ```
42
+
43
+ Most workflow classes return a normalized payload shaped like:
44
+
45
+ ```python
46
+ {
47
+ "input": {...},
48
+ "data": {...},
49
+ }
50
+ ```
51
+
52
+ `price` workflows support `price_fields="close"` (default), `price_fields="oclh"`, `price_fields="oclhv"`, `price_fields="oclhva"`, and comma-separated field lists such as `price_fields="volume,amount"` to control which price columns are returned. `PricePeriodWorkflow` also supports `price_source="krx"` when KRX `Amount` data is required for VWAP.
53
+
54
+ ### Workflow Classes
55
+
56
+ The main usage pattern is class-based:
57
+
58
+ - `MappingWorkflow`
59
+ - `PricePeriodWorkflow`
60
+ - `PriceSnapshotWorkflow`
61
+ - `FnGuideWorkflow`
62
+ - `MarketBondWorkflow`
63
+ - `KindWorkflow`
64
+
65
+ For example, `FnGuideWorkflow` is used like this:
66
+
67
+ ```python
68
+ from orchestrator.fnguide import FnGuideWorkflow
69
+
70
+ workflow = FnGuideWorkflow()
71
+ result = workflow.run(stock_code="005930", statement_type="consolidated")
72
+ ```
73
+
74
+ ### KIND Workflow
75
+
76
+ `kind` is slightly different from the other workflow modules because it supports both:
77
+
78
+ - request payload construction and raw response download
79
+ - HTML file parsing into structured JSON
80
+
81
+ The recommended entry point is `KindWorkflow`.
82
+
83
+ ```python
84
+ from pathlib import Path
85
+
86
+ from orchestrator.kind import KindWorkflow
87
+ from run import KIND_REQUEST_HEADERS
88
+
89
+ workflow = KindWorkflow()
90
+ result = workflow.run(
91
+ output_directory=Path("resources/kind_2012"),
92
+ request_headers=KIND_REQUEST_HEADERS,
93
+ start_date="2012-01-01",
94
+ end_date="2012-12-31",
95
+ start_page=1,
96
+ end_page=10,
97
+ disclosure_type_groups={"01": ["0119"]},
98
+ last_report_only=True,
99
+ save=True,
100
+ )
101
+
102
+ print(result["input_snapshot_path"])
103
+ print(result["checkpoint_path"])
104
+ ```
105
+
106
+ `KindWorkflow` stores normalized input state and, when `save=True`, writes:
107
+
108
+ - raw `.body` files page by page
109
+ - `kind_workflow.input.json`
110
+ - `kind_workflow.checkpoint.json`
111
+
112
+ This makes long-running downloads easier to inspect and recover.
113
+
114
+ Lower-level helpers remain available when needed:
115
+
116
+ ```python
117
+ from orchestrator.kind import (
118
+ build_kind_search_request_data,
119
+ parse_kind_file_to_json,
120
+ parse_kind_html_to_json,
121
+ save_kind_search_results,
122
+ )
123
+ ```
124
+
125
+ ### Example Script
126
+
127
+ `run.py` shows one concrete KIND pipeline:
128
+
129
+ 1. Download paged KIND responses through `KindWorkflow`
130
+ 2. Merge downloaded `.body` files into a single JSON file
131
+ 3. Convert the merged JSON into Excel using `utilitykit`
132
+
133
+ ## UtilityKit
134
+
135
+ `utilitykit` is a shared utilities package for repo-wide helpers that do not belong to `orchestrator`.
136
+
137
+ Current public utilities:
138
+
139
+ - `utilitykit.excel.read_xlsx_sheet_as_json()`
140
+ - `utilitykit.excel.write_json_to_xlsx()`
141
+ - `utilitykit.excel.records_to_table()`
142
+ - `utilitykit.excel.project_records_to_table()`
143
+ - `utilitykit.excel.row_cell_records_to_table()`
144
+
145
+ ### Excel Examples
146
+
147
+ Read an Excel sheet as `list[list]` using A1-start automatic bounds detection:
148
+
149
+ ```python
150
+ from utilitykit import read_xlsx_sheet_as_json
151
+
152
+ table = read_xlsx_sheet_as_json("sample.xlsx", sheet_name="Data")
153
+ ```
154
+
155
+ Write row-oriented data:
156
+
157
+ ```python
158
+ from utilitykit import write_json_to_xlsx
159
+
160
+ write_json_to_xlsx(
161
+ [
162
+ {"company": "Samsung", "sales": 100},
163
+ {"company": "LG", "sales": 80},
164
+ ],
165
+ "rows.xlsx",
166
+ sheet_name="Rows",
167
+ axis="rows",
168
+ item_mode="dict",
169
+ )
170
+ ```
171
+
172
+ Write column-oriented data:
173
+
174
+ ```python
175
+ from utilitykit import write_json_to_xlsx
176
+
177
+ write_json_to_xlsx(
178
+ {"company": ["Samsung", "LG"], "sales": [100, 80]},
179
+ "columns.xlsx",
180
+ sheet_name="Columns",
181
+ axis="columns",
182
+ item_mode="dict",
183
+ )
184
+ ```
185
+
186
+ ## TeleBotKit
187
+
188
+ `TeleBotKit` is a shared helper package that lives under `src/telebotkit` and is packaged together with this project.
189
+
190
+ It provides helpers for:
191
+
192
+ - Telegram bot command parsing, routing, MarkdownV2 escaping, and reply payload generation (`telebotkit.bot`)
193
+ - Firestore client bootstrap, typed repositories, shared document access, and lease/lock helpers (`telebotkit.firestore`)
194
+ - Excel row parsing and typed JSON payload generation for Firestore imports (`telebotkit.sheets`)
195
+
196
+ ### Example Usage
197
+
198
+ ```python
199
+ from telebotkit.bot import Reply, Router
200
+ from telebotkit.firestore import DocumentStore, get_client
201
+ from telebotkit.sheets import build_typed_rows_payload_from_xlsx
202
+ ```
203
+
204
+ See `src/telebotkit/README.md` for fuller API documentation and examples.
@@ -4,27 +4,47 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "financechatbotkit"
7
- version = "2.0.0"
7
+ version = "3.1.0"
8
8
  description = "FinanceChatbot workflows (orchestrator) and Telegram/Firestore helpers (TeleBotKit)"
9
9
  requires-python = ">=3.11"
10
+ readme = "README.md"
11
+
10
12
  dependencies = [
11
- "finance-datareader==0.9.110",
12
13
  "httpx>=0.27,<1",
14
+ "python-dotenv>=1,<2",
15
+ ]
16
+
17
+ [project.optional-dependencies]
18
+ orchestrator = [
19
+ "beautifulsoup4>=4.12,<5",
20
+ "finance-datareader==0.9.110",
21
+ "lxml>=5",
22
+ ]
23
+ firestore = [
13
24
  "google-cloud-firestore>=2.16.0",
14
25
  "google-api-core>=2.15.0",
15
26
  "google-auth>=2.28.0",
27
+ ]
28
+ excel = [
16
29
  "openpyxl>=3.1.0",
17
30
  ]
31
+ all = [
32
+ "financechatbotkit[orchestrator,firestore,excel]"
33
+ ]
34
+ dev = [
35
+ "pytest>=8",
36
+ "pytest-asyncio>=0.23",
37
+ ]
18
38
 
19
39
  [project.scripts]
20
- orchestrator-update-corp-codes = "orchestrator.mapping.update_raw_data:main"
40
+ orchestrator-update-corp-codes = "financechatbotkit.orchestrator.mapping.update_raw_data:main"
21
41
 
22
42
  [tool.setuptools]
23
43
  package-dir = {"" = "src"}
24
44
 
25
45
  [tool.setuptools.packages.find]
26
46
  where = ["src"]
27
- include = ["orchestrator*", "telebotkit*"]
47
+ include = ["financechatbotkit*"]
28
48
 
29
49
  [tool.setuptools.package-data]
30
- "orchestrator.mapping" = ["data/*.json"]
50
+ "financechatbotkit.orchestrator.mapping" = ["data/*.json"]
@@ -0,0 +1,90 @@
1
+ """FinanceChatbot workflow library."""
2
+
3
+ import importlib
4
+ from typing import TYPE_CHECKING
5
+
6
+ if TYPE_CHECKING:
7
+ from .bond import MarketBondWorkflow, run_market_bond_workflow
8
+ from .exceptions import DownloadError, InvalidInputError, MappingWorkflowError, NotFoundError
9
+ from .fnguide import FnGuideWorkflow, run_fnguide_workflow
10
+ from .kind import (
11
+ KindSavedFileCallback,
12
+ KindWorkflowCheckpoint,
13
+ KindWorkflow,
14
+ KindWorkflowInput,
15
+ ParseMode,
16
+ build_kind_search_request_data,
17
+ parse_kind_file_to_json,
18
+ parse_kind_html_to_json,
19
+ save_kind_search_results,
20
+ )
21
+ from .mapping import MappingWorkflow, run_mapping_workflow
22
+ from .price import (
23
+ PricePeriodWorkflow,
24
+ PriceSnapshotWorkflow,
25
+ run_price_period_workflow,
26
+ run_price_snapshot_workflow,
27
+ )
28
+
29
+ def __getattr__(name):
30
+ module_mapping = {
31
+ "MarketBondWorkflow": "bond",
32
+ "run_market_bond_workflow": "bond",
33
+ "DownloadError": "exceptions",
34
+ "InvalidInputError": "exceptions",
35
+ "MappingWorkflowError": "exceptions",
36
+ "NotFoundError": "exceptions",
37
+ "FnGuideWorkflow": "fnguide",
38
+ "run_fnguide_workflow": "fnguide",
39
+ "KindSavedFileCallback": "kind",
40
+ "KindWorkflowCheckpoint": "kind",
41
+ "KindWorkflow": "kind",
42
+ "KindWorkflowInput": "kind",
43
+ "ParseMode": "kind",
44
+ "build_kind_search_request_data": "kind",
45
+ "parse_kind_file_to_json": "kind",
46
+ "parse_kind_html_to_json": "kind",
47
+ "save_kind_search_results": "kind",
48
+ "MappingWorkflow": "mapping",
49
+ "run_mapping_workflow": "mapping",
50
+ "PricePeriodWorkflow": "price",
51
+ "PriceSnapshotWorkflow": "price",
52
+ "run_price_period_workflow": "price",
53
+ "run_price_snapshot_workflow": "price",
54
+ }
55
+
56
+ if name in module_mapping:
57
+ module_name = module_mapping[name]
58
+ module = importlib.import_module(f".{module_name}", package=__name__)
59
+ return getattr(module, name)
60
+
61
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
62
+
63
+ def __dir__():
64
+ return __all__
65
+
66
+ __all__ = [
67
+ "DownloadError",
68
+ "FnGuideWorkflow",
69
+ "InvalidInputError",
70
+ "KindSavedFileCallback",
71
+ "KindWorkflowCheckpoint",
72
+ "KindWorkflow",
73
+ "KindWorkflowInput",
74
+ "MappingWorkflow",
75
+ "MappingWorkflowError",
76
+ "MarketBondWorkflow",
77
+ "NotFoundError",
78
+ "ParseMode",
79
+ "PricePeriodWorkflow",
80
+ "PriceSnapshotWorkflow",
81
+ "build_kind_search_request_data",
82
+ "parse_kind_file_to_json",
83
+ "parse_kind_html_to_json",
84
+ "run_fnguide_workflow",
85
+ "run_market_bond_workflow",
86
+ "run_mapping_workflow",
87
+ "run_price_period_workflow",
88
+ "run_price_snapshot_workflow",
89
+ "save_kind_search_results",
90
+ ]
@@ -0,0 +1,21 @@
1
+ """Open DART 공시 API 클라이언트. 아직 미완성."""
2
+
3
+ from .zip_extractor import extract_dart_zip
4
+ from .api_client import DART_OPEN_API_BASE, fetch_dart_json, fetch_dart_bytes, fetch_dart
5
+ from .xml_to_dict import xml_markup_to_json, xml_to_soup
6
+ from .xml_to_tree import parse_dart_xml
7
+ from .tree_to_outline import build_outline_nested, iter_outline_from_structure, render_outline_lines
8
+
9
+ __all__ = [
10
+ "DART_OPEN_API_BASE",
11
+ "extract_dart_zip",
12
+ "fetch_dart",
13
+ "fetch_dart_bytes",
14
+ "fetch_dart_json",
15
+ "xml_markup_to_json",
16
+ "xml_to_soup",
17
+ "parse_dart_xml",
18
+ "build_outline_nested",
19
+ "iter_outline_from_structure",
20
+ "render_outline_lines",
21
+ ]
@@ -0,0 +1,66 @@
1
+ """Open DART (금융감독원 전자공시) API — 기본 httpx 동기 요청."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import logging
6
+ from typing import Any
7
+
8
+ import httpx
9
+
10
+ from ..exceptions import DownloadError
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+ DART_OPEN_API_BASE = "https://opendart.fss.or.kr/api"
15
+
16
+
17
+ def fetch_dart(
18
+ *,
19
+ path: str,
20
+ api_key: str,
21
+ params: dict[str, Any] | None = None,
22
+ timeout: float = 30.0,
23
+ ) -> httpx.Response:
24
+ """Open DART API에 GET 요청 후 응답 객체를 반환한다."""
25
+ url = f"{DART_OPEN_API_BASE}/{path.lstrip('/')}"
26
+ query: dict[str, Any] = {"crtfc_key": api_key}
27
+ if params:
28
+ query.update(params)
29
+
30
+ try:
31
+ response = httpx.get(
32
+ url,
33
+ params=query,
34
+ timeout=timeout,
35
+ follow_redirects=True,
36
+ )
37
+ response.raise_for_status()
38
+ except httpx.HTTPError as exc:
39
+ logger.warning("DART request failed for %s: %s", url, exc)
40
+ raise DownloadError(f"Failed to fetch DART API: {url}") from exc
41
+
42
+ return response
43
+
44
+
45
+ def fetch_dart_json(
46
+ *,
47
+ path: str,
48
+ api_key: str,
49
+ params: dict[str, Any] | None = None,
50
+ timeout: float = 30.0,
51
+ ) -> dict[str, Any]:
52
+ """Open DART API에 GET 요청 후 JSON을 파싱해 반환한다."""
53
+ response = fetch_dart(path=path, api_key=api_key, params=params, timeout=timeout)
54
+ return response.json()
55
+
56
+
57
+ def fetch_dart_bytes(
58
+ *,
59
+ path: str,
60
+ api_key: str,
61
+ params: dict[str, Any] | None = None,
62
+ timeout: float = 30.0,
63
+ ) -> bytes:
64
+ """Open DART API에 GET 요청 후 바이너리(Bytes)를 반환한다."""
65
+ response = fetch_dart(path=path, api_key=api_key, params=params, timeout=timeout)
66
+ return response.content