earningscall 0.0.12__py3-none-any.whl → 0.0.14__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.
earningscall/__init__.py CHANGED
@@ -4,5 +4,6 @@ from earningscall.exports import get_company, get_all_companies, get_sp500_compa
4
4
  from earningscall.symbols import Symbols, load_symbols
5
5
 
6
6
  api_key: Optional[str] = None
7
+ enable_requests_cache: bool = True
7
8
 
8
9
  __all__ = ["get_company", "get_all_companies", "get_sp500_companies", "Symbols", "load_symbols"]
earningscall/api.py CHANGED
@@ -3,6 +3,7 @@ import os
3
3
  from typing import Optional
4
4
 
5
5
  import requests
6
+ from requests_cache import CachedSession
6
7
 
7
8
  import earningscall
8
9
 
@@ -27,15 +28,45 @@ def is_demo_account():
27
28
  return get_api_key() == "demo"
28
29
 
29
30
 
30
- def get_events(exchange: str, symbol: str):
31
+ def cache_session() -> CachedSession:
32
+ return CachedSession(
33
+ ".earningscall_cache",
34
+ backend="sqlite",
35
+ cache_control=True,
36
+ use_temp=True,
37
+ ignored_parameters=['apikey'],
38
+ )
39
+
40
+
41
+ def cached_urls():
42
+ return cache_session().cache.urls()
43
+
44
+
45
+ def purge_cache():
46
+ return cache_session().cache.clear()
47
+
48
+
49
+ def do_get(path: str, use_cache: bool = False, **kwargs):
50
+ params = {
51
+ **api_key_param(),
52
+ **kwargs.get("params", {}),
53
+ }
54
+ url = f"{API_BASE}/{path}"
55
+ log.debug(f"do_get url: {url} params: {params}")
56
+ if use_cache and earningscall.enable_requests_cache:
57
+ return cache_session().get(url, params=params)
58
+ else:
59
+ return requests.get(url, params=params)
31
60
 
61
+
62
+ def get_events(exchange: str, symbol: str):
32
63
  log.debug(f"get_events exchange: {exchange} symbol: {symbol}")
33
64
  params = {
34
65
  **api_key_param(),
35
66
  "exchange": exchange,
36
67
  "symbol": symbol,
37
68
  }
38
- response = requests.get(f"{API_BASE}/events", params=params)
69
+ response = do_get("events", params=params)
39
70
  if response.status_code != 200:
40
71
  return None
41
72
  return response.json()
@@ -51,34 +82,23 @@ def get_transcript(exchange: str, symbol: str, year: int, quarter: int) -> Optio
51
82
  "year": str(year),
52
83
  "quarter": str(quarter),
53
84
  }
54
- response = requests.get(f"{API_BASE}/transcript", params=params)
85
+ response = do_get("transcript", params=params)
55
86
  if response.status_code != 200:
56
87
  return None
57
88
  return response.json()
58
89
 
59
90
 
60
- def get_symbols_v1():
61
- response = requests.get(f"{API_BASE}/symbols.txt")
62
- if response.status_code != 200:
63
- return None
64
- return response.text
65
-
66
-
67
91
  def get_symbols_v2():
68
- response = requests.get(f"{API_BASE}/symbols-v2.txt", params=api_key_param())
92
+ log.debug("get_symbols_v2")
93
+ response = do_get("symbols-v2.txt", use_cache=True)
69
94
  if response.status_code != 200:
70
95
  return None
71
96
  return response.text
72
97
 
73
98
 
74
99
  def get_sp500_companies_txt_file():
75
- response = requests.get(f"{API_BASE}/symbols/sp500.txt", params=api_key_param())
100
+ log.debug("get_sp500_companies_txt_file")
101
+ response = do_get("symbols/sp500.txt", use_cache=True)
76
102
  if response.status_code != 200:
77
103
  return None
78
104
  return response.text
79
-
80
-
81
- # def do_something():
82
- # session = CachedSession('demo_cache', cache_control=True)
83
- #
84
- # # CachedSession()
earningscall/sectors.py CHANGED
@@ -1,6 +1,4 @@
1
- import json
2
1
  import logging
3
- from typing import Optional
4
2
 
5
3
  log = logging.getLogger(__file__)
6
4
  sectors_file_name = "sectors.json"
@@ -179,14 +177,20 @@ def sector_to_index(_sector: str) -> int:
179
177
 
180
178
  def index_to_sector(_index: int) -> str:
181
179
  if _index == -1:
182
- return "UNKNOWN"
183
- return SECTORS_IN_ORDER[_index]
180
+ return "Unknown"
181
+ try:
182
+ return SECTORS_IN_ORDER[_index]
183
+ except IndexError:
184
+ return "Unknown"
184
185
 
185
186
 
186
187
  def index_to_industry(_index: int) -> str:
187
188
  if _index == -1:
188
- return "UNKNOWN"
189
- return INDUSTRIES_IN_ORDER[_index]
189
+ return "Unknown"
190
+ try:
191
+ return INDUSTRIES_IN_ORDER[_index]
192
+ except IndexError:
193
+ return "Unknown"
190
194
 
191
195
 
192
196
  def industry_to_index(_industry: str) -> int:
@@ -194,38 +198,3 @@ def industry_to_index(_industry: str) -> int:
194
198
  return INDUSTRIES_IN_ORDER.index(_industry)
195
199
  except ValueError:
196
200
  return -1
197
-
198
-
199
- class Sectors:
200
-
201
- def __init__(self, sectors: Optional[set] = None, industries: Optional[set] = None):
202
- if sectors:
203
- self.sectors = sectors
204
- else:
205
- self.sectors = set()
206
- if industries:
207
- self.industries = industries
208
- else:
209
- self.industries = set()
210
-
211
- def add_sector(self, sector: str):
212
- if sector is not None:
213
- self.sectors.add(sector)
214
-
215
- def add_industry(self, industry: str):
216
- if industry is not None:
217
- self.industries.add(industry)
218
-
219
- def to_dicts(self) -> dict:
220
- return {
221
- "sectors": list(self.sectors),
222
- "industries": list(self.industries),
223
- }
224
-
225
- def to_json(self) -> str:
226
- return json.dumps(self.to_dicts())
227
-
228
- @staticmethod
229
- def from_json(json_str):
230
- data = json.loads(json_str)
231
- return Sectors(set(data["sectors"]), set(data["industries"]))
earningscall/symbols.py CHANGED
@@ -1,6 +1,5 @@
1
1
  import json
2
2
  import logging
3
- import re
4
3
  from collections import defaultdict
5
4
  from typing import Optional, Iterator, List
6
5
 
@@ -26,7 +25,10 @@ def exchange_to_index(_exchange: Optional[str]) -> int:
26
25
  def index_to_exchange(_index: int) -> str:
27
26
  if _index == -1:
28
27
  return "UNKNOWN"
29
- return EXCHANGES_IN_ORDER[_index]
28
+ try:
29
+ return EXCHANGES_IN_ORDER[_index]
30
+ except IndexError:
31
+ return "UNKNOWN"
30
32
 
31
33
 
32
34
  security_type_pattern = {
@@ -47,21 +49,12 @@ class CompanyInfo:
47
49
 
48
50
  def __init__(self, **kwargs):
49
51
  self.exchange = None
52
+ self.symbol = None
50
53
  self.name = None
51
- self.security_name = None
52
54
  self.sector = None
53
55
  self.industry = None
54
56
  for key, value in kwargs.items():
55
57
  self.__setattr__(key, value)
56
- # If name is not set upon initialization, we'll set it from the security name. Also, include
57
- # sanitization (removing "Common Stock" from the security name for example)
58
- if not self.name:
59
- if self.exchange == "OTC":
60
- self.security_name = self.security_name.title()
61
- if self.exchange in security_type_pattern:
62
- self.name = re.sub(security_type_pattern[self.exchange], "", self.security_name)
63
- else:
64
- self.name = self.security_name
65
58
 
66
59
  def __str__(self):
67
60
  return f"({self.exchange}: {self.symbol} - {self.name})"
@@ -160,20 +153,6 @@ class Symbols:
160
153
  return json.dumps(self.without_security_names())
161
154
  return json.dumps(self.to_dicts())
162
155
 
163
- # TODO: Test this
164
- # def to_json_v2(self) -> str:
165
- # return json.dumps(
166
- # [
167
- # [exchange_to_index(__symbol.exchange), __symbol.company_info, __symbol.name]
168
- # for __symbol in self.get_all()
169
- # ]
170
- # )
171
-
172
- def to_txt(self) -> str:
173
- exchange_symbol_names = [__symbol.to_txt_row() for __symbol in self.get_all()]
174
- sorted_rows = sorted(exchange_symbol_names, key=lambda row: row[1])
175
- return "\n".join(["\t".join(row) for row in sorted_rows])
176
-
177
156
  def to_txt_v2(self) -> str:
178
157
  exchange_symbol_names = [__symbol.to_txt_v2_row() for __symbol in self.get_all()]
179
158
  sorted_rows = sorted(exchange_symbol_names, key=lambda row: row[1])
@@ -186,21 +165,6 @@ class Symbols:
186
165
  __symbols.add(CompanyInfo(**item))
187
166
  return __symbols
188
167
 
189
- @staticmethod
190
- def from_json_v2(json_str):
191
- __symbols = Symbols()
192
- for [_exchange_index, _symbol, _name] in json.loads(json_str):
193
- __symbols.add(CompanyInfo(exchange=index_to_exchange(_exchange_index), symbol=_symbol, name=_name))
194
- return __symbols
195
-
196
- @staticmethod
197
- def from_txt(txt_str):
198
- __symbols = Symbols()
199
- for line in txt_str.split("\n"):
200
- _exchange_index, _symbol, _name = line.split("\t")
201
- __symbols.add(CompanyInfo(exchange=index_to_exchange(int(_exchange_index)), symbol=_symbol, name=_name))
202
- return __symbols
203
-
204
168
  @staticmethod
205
169
  def from_txt_v2(txt_str):
206
170
  __symbols = Symbols()
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: earningscall
3
- Version: 0.0.12
4
- Summary: The EarningsCall Python library.
3
+ Version: 0.0.14
4
+ Summary: The EarningsCall Python library provides convenient access to the EarningsCall API. It includes a pre-defined set of classes for API resources that initialize themselves dynamically from API responses.
5
5
  Project-URL: Homepage, https://earningscall.biz
6
6
  Project-URL: Documentation, https://github.com/EarningsCall/earningscall-python
7
7
  Project-URL: Repository, https://github.com/EarningsCall/earningscall-python
@@ -31,6 +31,18 @@ License: MIT License
31
31
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32
32
  SOFTWARE.
33
33
  License-File: LICENSE
34
+ Keywords: earnings call,earnings call transcripts,earnings calls,transcripts
35
+ Classifier: Development Status :: 3 - Alpha
36
+ Classifier: Intended Audience :: Developers
37
+ Classifier: License :: OSI Approved :: MIT License
38
+ Classifier: Programming Language :: Python :: 3
39
+ Classifier: Programming Language :: Python :: 3.8
40
+ Classifier: Programming Language :: Python :: 3.9
41
+ Classifier: Programming Language :: Python :: 3.10
42
+ Classifier: Programming Language :: Python :: 3.11
43
+ Classifier: Programming Language :: Python :: 3.12
44
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
45
+ Classifier: Typing :: Typed
34
46
  Requires-Python: >=3.8
35
47
  Requires-Dist: dataclasses-json>=0.6.4
36
48
  Requires-Dist: dataclasses>=0.6
@@ -40,15 +52,20 @@ Description-Content-Type: text/markdown
40
52
 
41
53
  # EarningsCall Python Library
42
54
 
43
- [![pypi](https://img.shields.io/pypi/v/earningscall.svg)](https://pypi.python.org/pypi/earningscall)
55
+ [![pypi](https://img.shields.io/pypi/v/earningscall.svg)](https://pypi.org/project/earningscall/)
44
56
  [![Build Status](https://github.com/EarningsCall/earningscall-python/actions/workflows/release.yml/badge.svg?branch=master)](https://github.com/EarningsCall/earningscall-python/actions?query=branch%3Amaster)
45
57
  [![Coverage Status](https://coveralls.io/repos/github/EarningsCall/earningscall-python/badge.svg?branch=master)](https://coveralls.io/github/EarningsCall/earningscall-python?branch=master)
58
+ [![PyPI - Downloads](https://img.shields.io/pypi/dm/earningscall?color=blue)](https://pypi.org/project/earningscall/)
46
59
 
47
60
  The EarningsCall Python library provides convenient access to the [EarningsCall API](https://earningscall.biz/api-guide) from
48
61
  applications written in the Python language. It includes a pre-defined set of
49
62
  classes for API resources that initialize themselves dynamically from API
50
63
  responses.
51
64
 
65
+ # Requirements
66
+
67
+ * Python 3.8+
68
+
52
69
  # Installation
53
70
 
54
71
  You don't need this source code unless you want to modify the package. If you just want to use the package, just run:
@@ -57,10 +74,6 @@ You don't need this source code unless you want to modify the package. If you ju
57
74
  pip install --upgrade earningscall
58
75
  ```
59
76
 
60
- # Requirements
61
-
62
- * Python 3.8+ (PyPI supported)
63
-
64
77
  ## Get Transcript for a Single Quarter
65
78
 
66
79
  ```python
@@ -151,3 +164,18 @@ for company in get_sp500_companies():
151
164
  print(f"{company.company_info} -- {company.company_info.sector} -- {company.company_info.industry}")
152
165
  ```
153
166
 
167
+
168
+ ## Advanced
169
+
170
+ ### Disable Caching
171
+
172
+ When you call `get_company("aapl")` to retrieve a company, internally the library retrieves metadata
173
+ from the EarningsCall API. By default, it caches this metadata on disk in order to speed up subsequent requests.
174
+
175
+ If you prefer to disable this local caching behavior, you can do so with this code:
176
+
177
+ ```python
178
+ import earningscall
179
+
180
+ earningscall.enable_requests_cache = False
181
+ ```
@@ -0,0 +1,14 @@
1
+ earningscall/__init__.py,sha256=0mANmPlE7LEWtOGzV2cmmlPfBIWBWlWRDkyqPHJ1jm8,333
2
+ earningscall/api.py,sha256=guyKJCg949sRYP9FuIUfgo93u6jfC_9wSgJBXVAEwIg,2496
3
+ earningscall/company.py,sha256=ZNF75htXg37oXtNzwrHH8DoTdyFJ3PBB9qSNBp_vo8c,1943
4
+ earningscall/errors.py,sha256=EA-d6qIYgQs9csp8JptQiAaYoM0M9HhCGJgKA9GAWPg,440
5
+ earningscall/event.py,sha256=O7KAE2wO3mBhlEWIFA1choMNGRthYd0gBIvVQOmVALs,692
6
+ earningscall/exports.py,sha256=i9UWHY6Lq1OzZTZX_1SdNzrNd_PSlPwpB337lGMK4oM,837
7
+ earningscall/sectors.py,sha256=Xd6DLkAQ_fQkC2s-N9pReC8b_M3iy77OoFftoZj9FWY,5114
8
+ earningscall/symbols.py,sha256=Fsk9F2SYzn5TUQnL84AO1_xgiMg6G1DyvBGm7-_3LH4,6347
9
+ earningscall/transcript.py,sha256=rLH2bGrrgUmS8XZGAPUP7msiIcL7f4ABmbnVJWXI28c,329
10
+ earningscall/utils.py,sha256=Qx8KhlumUdzyBSZRKMS6vpWlb8MGZpLKA4OffJaMdCE,1032
11
+ earningscall-0.0.14.dist-info/METADATA,sha256=n7yhm8mMOfEblfEMjNsRMD1WM8LXB4kQlsRt_IY4Dpo,7014
12
+ earningscall-0.0.14.dist-info/WHEEL,sha256=zEMcRr9Kr03x1ozGwg5v9NQBKn3kndp6LSoSlVg-jhU,87
13
+ earningscall-0.0.14.dist-info/licenses/LICENSE,sha256=ktEB_UcRMg2cQlX9wiDs544xWncWizwS9mEZuGsCLrM,1069
14
+ earningscall-0.0.14.dist-info/RECORD,,
@@ -1,14 +0,0 @@
1
- earningscall/__init__.py,sha256=NX9f2et-q3p8BRGvJB0enRSLlSGecSAwspPxhDsL95Y,298
2
- earningscall/api.py,sha256=eK43JazoBNI9YF0OMi5c0DrYv0tVzyOy2ycNyX63y8s,2000
3
- earningscall/company.py,sha256=ZNF75htXg37oXtNzwrHH8DoTdyFJ3PBB9qSNBp_vo8c,1943
4
- earningscall/errors.py,sha256=EA-d6qIYgQs9csp8JptQiAaYoM0M9HhCGJgKA9GAWPg,440
5
- earningscall/event.py,sha256=O7KAE2wO3mBhlEWIFA1choMNGRthYd0gBIvVQOmVALs,692
6
- earningscall/exports.py,sha256=i9UWHY6Lq1OzZTZX_1SdNzrNd_PSlPwpB337lGMK4oM,837
7
- earningscall/sectors.py,sha256=9kAwTtJEDbWah6lz5io88qRwvCtmGgjQ-MU7rayTmVI,5962
8
- earningscall/symbols.py,sha256=EXSPUMr50zZz-Cw9CimrRbVd7F71PB9McgsFC7yJ5S4,7980
9
- earningscall/transcript.py,sha256=rLH2bGrrgUmS8XZGAPUP7msiIcL7f4ABmbnVJWXI28c,329
10
- earningscall/utils.py,sha256=Qx8KhlumUdzyBSZRKMS6vpWlb8MGZpLKA4OffJaMdCE,1032
11
- earningscall-0.0.12.dist-info/METADATA,sha256=Br6DJz0J0ZVy4FrY6qkSYcFoze_unf2ooht9v7D__UQ,5714
12
- earningscall-0.0.12.dist-info/WHEEL,sha256=zEMcRr9Kr03x1ozGwg5v9NQBKn3kndp6LSoSlVg-jhU,87
13
- earningscall-0.0.12.dist-info/licenses/LICENSE,sha256=ktEB_UcRMg2cQlX9wiDs544xWncWizwS9mEZuGsCLrM,1069
14
- earningscall-0.0.12.dist-info/RECORD,,