unique-quartr 0.2.6__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.
- unique_quartr-0.2.6/PKG-INFO +576 -0
- unique_quartr-0.2.6/README.md +560 -0
- unique_quartr-0.2.6/pyproject.toml +72 -0
- unique_quartr-0.2.6/unique_quartr/__init__.py +0 -0
- unique_quartr-0.2.6/unique_quartr/constants/document_types.py +75 -0
- unique_quartr-0.2.6/unique_quartr/constants/event_types.py +151 -0
- unique_quartr-0.2.6/unique_quartr/endpoints/api.py +70 -0
- unique_quartr-0.2.6/unique_quartr/endpoints/schemas.py +724 -0
- unique_quartr-0.2.6/unique_quartr/service.py +210 -0
- unique_quartr-0.2.6/unique_quartr/settings.py +56 -0
- unique_quartr-0.2.6/unique_quartr/transcripts/earnings_call/__init__.py +3 -0
- unique_quartr-0.2.6/unique_quartr/transcripts/earnings_call/schema.py +130 -0
- unique_quartr-0.2.6/unique_quartr/transcripts/earnings_call/transcript_template.j2 +14 -0
|
@@ -0,0 +1,576 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: unique-quartr
|
|
3
|
+
Version: 0.2.6
|
|
4
|
+
Summary: Unique Quartr API client
|
|
5
|
+
Author: Rami Azouz
|
|
6
|
+
Author-email: Rami Azouz <rami.ext@unique.ch>
|
|
7
|
+
License: Proprietary
|
|
8
|
+
Requires-Dist: unique-toolkit>=1.50.4
|
|
9
|
+
Requires-Dist: pydantic>=2.12.4
|
|
10
|
+
Requires-Dist: pydantic-settings>=2.10.1
|
|
11
|
+
Requires-Dist: jinja2>=3.1.0
|
|
12
|
+
Requires-Dist: httpx>=0.28.0
|
|
13
|
+
Requires-Dist: requests>=2.32.0
|
|
14
|
+
Requires-Python: >=3.12, <4
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
|
|
17
|
+
# Unique Quartr Connector
|
|
18
|
+
|
|
19
|
+
A Python connector library for the [Quartr API](https://quartr.com), providing easy access to company events, documents, and financial data.
|
|
20
|
+
|
|
21
|
+
## Features
|
|
22
|
+
|
|
23
|
+
- 🔍 Fetch company earnings calls and events
|
|
24
|
+
- 📄 Retrieve event documents (transcripts, reports, slides, etc.)
|
|
25
|
+
- 📝 Parse and export earnings call transcripts to markdown
|
|
26
|
+
- 🎯 Type-safe API with Pydantic models
|
|
27
|
+
- 🔄 Automatic pagination handling
|
|
28
|
+
- 📊 Support for multiple document and event types
|
|
29
|
+
- 🔐 Secure API key authentication with base64 encoding
|
|
30
|
+
|
|
31
|
+
## Installation
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
poetry add unique_quartr
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Or using pip:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pip install unique_quartr
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Configuration
|
|
44
|
+
|
|
45
|
+
### Environment Variables
|
|
46
|
+
|
|
47
|
+
Create a `.env` file in your project root with your Quartr API credentials:
|
|
48
|
+
|
|
49
|
+
```env
|
|
50
|
+
# Base64-encoded JSON credentials
|
|
51
|
+
QUARTR_API_CREDS='xxxxxxxxxxx'
|
|
52
|
+
QUARTR_API_ACTIVATED_COMPANIES='["company_id_1", "company_id_2"]'
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Note**: The `QUARTR_API_CREDS` should be a base64-encoded JSON string containing:
|
|
56
|
+
```json
|
|
57
|
+
{"api_key": "your_api_key_here", "valid_to": "2025-12-31"}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
You can encode your credentials using:
|
|
61
|
+
```python
|
|
62
|
+
import base64
|
|
63
|
+
import json
|
|
64
|
+
|
|
65
|
+
creds = {"api_key": "your_api_key_here", "valid_to": "2025-12-31"}
|
|
66
|
+
encoded = base64.b64encode(json.dumps(creds).encode()).decode()
|
|
67
|
+
print(encoded)
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Test Environment
|
|
71
|
+
|
|
72
|
+
For testing, create `tests/test.env`:
|
|
73
|
+
|
|
74
|
+
```env
|
|
75
|
+
QUARTR_API_CREDS='xxxxxxxxxxx'
|
|
76
|
+
QUARTR_API_ACTIVATED_COMPANIES='["test_company"]'
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Quick Start
|
|
80
|
+
|
|
81
|
+
### Basic Usage
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
from unique_quartr.service import QuartrService
|
|
85
|
+
from unique_quartr.constants.event_types import EventType
|
|
86
|
+
from unique_quartr.constants.document_types import DocumentType
|
|
87
|
+
from unique_toolkit._common.experimental.endpoint_requestor import RequestorType
|
|
88
|
+
|
|
89
|
+
# Initialize the service
|
|
90
|
+
service = QuartrService(
|
|
91
|
+
company_id="your_company_id",
|
|
92
|
+
requestor_type=RequestorType.REQUESTS,
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
# Define the event types you want to fetch
|
|
96
|
+
event_types = [EventType.EARNINGS_CALL]
|
|
97
|
+
event_ids = service.get_event_subtype_ids_from_event_types(event_types)
|
|
98
|
+
|
|
99
|
+
# Fetch company events
|
|
100
|
+
events = service.fetch_company_events(
|
|
101
|
+
ticker="AAPL",
|
|
102
|
+
exchange="NasdaqGS",
|
|
103
|
+
country="US",
|
|
104
|
+
event_ids=event_ids,
|
|
105
|
+
start_date="2024-01-01",
|
|
106
|
+
end_date="2024-12-31",
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
print(f"Found {len(events.data)} events")
|
|
110
|
+
for event in events.data:
|
|
111
|
+
print(f"Event: {event.title} - {event.date}")
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Fetching Documents
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
# Get event IDs from the events you fetched
|
|
118
|
+
event_ids = [event.id for event in events.data]
|
|
119
|
+
|
|
120
|
+
# Define document types you want
|
|
121
|
+
document_types = [DocumentType.TRANSCRIPT, DocumentType.SLIDES]
|
|
122
|
+
document_ids = service.get_document_ids_from_document_types(document_types)
|
|
123
|
+
|
|
124
|
+
# Fetch documents for these events
|
|
125
|
+
documents = service.fetch_event_documents(
|
|
126
|
+
event_ids=event_ids,
|
|
127
|
+
document_ids=document_ids,
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
print(f"Found {len(documents.data)} documents")
|
|
131
|
+
for doc in documents.data:
|
|
132
|
+
print(f"Document: {doc.type_id} - {doc.file_url}")
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Working with Earnings Call Transcripts
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
from unique_quartr.transcripts.earnings_call import QuartrEarningsCallTranscript
|
|
139
|
+
|
|
140
|
+
# Fetch transcript from Quartr URL
|
|
141
|
+
transcript_url = "https://quartr.com/transcript/12345.json"
|
|
142
|
+
transcript = QuartrEarningsCallTranscript.from_quartr_transcript_url(transcript_url)
|
|
143
|
+
|
|
144
|
+
# Or use async version
|
|
145
|
+
transcript = await QuartrEarningsCallTranscript.from_quartr_transcript_url_async(transcript_url)
|
|
146
|
+
|
|
147
|
+
# Export to markdown
|
|
148
|
+
markdown_content = transcript.to_markdown()
|
|
149
|
+
print(markdown_content)
|
|
150
|
+
|
|
151
|
+
# Access transcript data
|
|
152
|
+
print(f"Event ID: {transcript.event_id}")
|
|
153
|
+
print(f"Company ID: {transcript.company_id}")
|
|
154
|
+
print(f"Number of speakers: {transcript.transcript.number_of_speakers}")
|
|
155
|
+
|
|
156
|
+
# Iterate through paragraphs
|
|
157
|
+
for paragraph in transcript.transcript.paragraphs:
|
|
158
|
+
speaker_name = transcript._get_speaker_name(paragraph.speaker)
|
|
159
|
+
print(f"{speaker_name}: {paragraph.text[:100]}...")
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Event Types
|
|
163
|
+
|
|
164
|
+
The library supports the following event types:
|
|
165
|
+
|
|
166
|
+
- **Earnings Call**: Q1, Q2, Q3, Q4, H1, H2
|
|
167
|
+
- **Analyst Day**
|
|
168
|
+
- **Annual General Meeting**: AGM, Scheme Meeting
|
|
169
|
+
- **Business Combination**
|
|
170
|
+
- **C-level Sitdown**: C-level Sitdown, CEO Sitdown
|
|
171
|
+
- **Capital Markets Day**
|
|
172
|
+
- **Capital Raise**
|
|
173
|
+
- **Conference**
|
|
174
|
+
- **Extraordinary General Meeting**
|
|
175
|
+
- **FDA Announcement**
|
|
176
|
+
- **Fireside Chat**
|
|
177
|
+
- **Investor Day**
|
|
178
|
+
- **M&A Announcement**
|
|
179
|
+
- **Outlook / Guidance Update**
|
|
180
|
+
- **Partnerships / Collaborations**: Partnership, Collaboration
|
|
181
|
+
- **Product / Service Launch**: Product Launch, Service Launch
|
|
182
|
+
- **Slides**: Investor Presentation, Corporate Presentation, Company Presentation
|
|
183
|
+
- **Trading Update**
|
|
184
|
+
- **Update / Briefing**: Status Update, Investor Update, ESG Update, Study Update, Study Result, KOL Event
|
|
185
|
+
|
|
186
|
+
### Example: Getting Earnings Call Event IDs
|
|
187
|
+
|
|
188
|
+
```python
|
|
189
|
+
from unique_quartr.constants.event_types import EventType
|
|
190
|
+
|
|
191
|
+
event_types = [EventType.EARNINGS_CALL]
|
|
192
|
+
event_ids = QuartrService.get_event_subtype_ids_from_event_types(event_types)
|
|
193
|
+
# Returns: [26, 27, 28, 29, 35, 36] (Q1, Q2, Q3, Q4, H1, H2)
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Document Types
|
|
197
|
+
|
|
198
|
+
The library supports various document types:
|
|
199
|
+
|
|
200
|
+
- **Slides** 📊
|
|
201
|
+
- **Report** 📄
|
|
202
|
+
- **Quarterly Report (10-Q)** 📑
|
|
203
|
+
- **Earnings Release (8-K)** 📢
|
|
204
|
+
- **Annual Report (10-K)** 📘
|
|
205
|
+
- **Annual Report (20-F)** 📙
|
|
206
|
+
- **Annual Report (40-F)** 📕
|
|
207
|
+
- **Earnings Release (6-K)** 📣
|
|
208
|
+
- **Transcript** 🗒️
|
|
209
|
+
- **Interim Report** 📜
|
|
210
|
+
- **Press Release** 🗞️
|
|
211
|
+
- **Earnings Release** 💰
|
|
212
|
+
- **In-house Transcript** 🎤
|
|
213
|
+
|
|
214
|
+
### Example: Getting Document Type Information
|
|
215
|
+
|
|
216
|
+
```python
|
|
217
|
+
from unique_quartr.constants.document_types import DocumentType
|
|
218
|
+
|
|
219
|
+
doc_type = DocumentType.QUARTERLY_REPORT_10Q
|
|
220
|
+
|
|
221
|
+
print(doc_type.name) # "Quarterly report"
|
|
222
|
+
print(doc_type.form) # "10-Q"
|
|
223
|
+
print(doc_type.emoji) # "📑"
|
|
224
|
+
print(doc_type.get_file_prefix()) # "Quarterly report (10-Q)"
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
## Advanced Usage
|
|
228
|
+
|
|
229
|
+
### Custom Pagination
|
|
230
|
+
|
|
231
|
+
Control pagination parameters for large datasets:
|
|
232
|
+
|
|
233
|
+
```python
|
|
234
|
+
events = service.fetch_company_events(
|
|
235
|
+
ticker="AAPL",
|
|
236
|
+
exchange="NasdaqGS",
|
|
237
|
+
country="US",
|
|
238
|
+
event_ids=event_ids,
|
|
239
|
+
limit=100, # Items per page (max 500)
|
|
240
|
+
max_iteration=10, # Maximum number of pages
|
|
241
|
+
)
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Filtering by Date Range
|
|
245
|
+
|
|
246
|
+
```python
|
|
247
|
+
events = service.fetch_company_events(
|
|
248
|
+
ticker="AAPL",
|
|
249
|
+
exchange="NasdaqGS",
|
|
250
|
+
country="US",
|
|
251
|
+
event_ids=event_ids,
|
|
252
|
+
start_date="2024-01-01T00:00:00Z", # ISO format
|
|
253
|
+
end_date="2024-03-31T23:59:59Z",
|
|
254
|
+
)
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### Fetching Multiple Event Types
|
|
258
|
+
|
|
259
|
+
```python
|
|
260
|
+
from unique_quartr.constants.event_types import EventType
|
|
261
|
+
|
|
262
|
+
# Combine multiple event types
|
|
263
|
+
event_types = [
|
|
264
|
+
EventType.EARNINGS_CALL,
|
|
265
|
+
EventType.ANALYST_DAY,
|
|
266
|
+
EventType.INVESTOR_DAY,
|
|
267
|
+
]
|
|
268
|
+
|
|
269
|
+
event_ids = QuartrService.get_event_subtype_ids_from_event_types(event_types)
|
|
270
|
+
|
|
271
|
+
events = service.fetch_company_events(
|
|
272
|
+
ticker="AAPL",
|
|
273
|
+
exchange="NasdaqGS",
|
|
274
|
+
country="US",
|
|
275
|
+
event_ids=event_ids,
|
|
276
|
+
)
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
## API Reference
|
|
280
|
+
|
|
281
|
+
### QuartrService
|
|
282
|
+
|
|
283
|
+
```python
|
|
284
|
+
class QuartrService:
|
|
285
|
+
def __init__(
|
|
286
|
+
self,
|
|
287
|
+
*,
|
|
288
|
+
company_id: str,
|
|
289
|
+
requestor_type: RequestorType,
|
|
290
|
+
):
|
|
291
|
+
"""
|
|
292
|
+
Initialize the Quartr service.
|
|
293
|
+
|
|
294
|
+
Args:
|
|
295
|
+
company_id: Company identifier for API access
|
|
296
|
+
requestor_type: Type of requestor (SYNC or ASYNC)
|
|
297
|
+
"""
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
#### Methods
|
|
301
|
+
|
|
302
|
+
##### fetch_company_events
|
|
303
|
+
|
|
304
|
+
```python
|
|
305
|
+
# Method signature (overloaded)
|
|
306
|
+
def fetch_company_events(
|
|
307
|
+
self,
|
|
308
|
+
*,
|
|
309
|
+
company_ids: list[int | float] | None = None,
|
|
310
|
+
ticker: str | None = None,
|
|
311
|
+
exchange: str | None = None,
|
|
312
|
+
country: str | None = None,
|
|
313
|
+
event_ids: list[int] | None = None,
|
|
314
|
+
start_date: str | None = None,
|
|
315
|
+
end_date: str | None = None,
|
|
316
|
+
limit: int = 500,
|
|
317
|
+
max_iteration: int = 20,
|
|
318
|
+
) -> EventResults:
|
|
319
|
+
"""
|
|
320
|
+
Retrieve events for a given company.
|
|
321
|
+
|
|
322
|
+
Args:
|
|
323
|
+
company_ids: List of company IDs (alternative to ticker/exchange/country)
|
|
324
|
+
ticker: Company ticker symbol (e.g., 'AAPL', 'AMZN')
|
|
325
|
+
exchange: Exchange code (e.g., 'NasdaqGS', 'NYSE')
|
|
326
|
+
country: Country code (e.g., 'US', 'CA')
|
|
327
|
+
event_ids: List of event type IDs to filter
|
|
328
|
+
start_date: Optional start date in ISO format
|
|
329
|
+
end_date: Optional end date in ISO format
|
|
330
|
+
limit: Items per request (max 500)
|
|
331
|
+
max_iteration: Maximum number of pagination iterations
|
|
332
|
+
|
|
333
|
+
Returns:
|
|
334
|
+
EventResults object with .data containing list of EventDto objects
|
|
335
|
+
|
|
336
|
+
Note:
|
|
337
|
+
Either company_ids OR (ticker, exchange, country) must be provided
|
|
338
|
+
"""
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
**Example with company IDs:**
|
|
342
|
+
```python
|
|
343
|
+
events = service.fetch_company_events(
|
|
344
|
+
company_ids=[4742, 5025],
|
|
345
|
+
event_ids=event_ids,
|
|
346
|
+
start_date="2024-01-01",
|
|
347
|
+
)
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
**Example with ticker/exchange:**
|
|
351
|
+
```python
|
|
352
|
+
events = service.fetch_company_events(
|
|
353
|
+
ticker="AAPL",
|
|
354
|
+
exchange="NasdaqGS",
|
|
355
|
+
country="US",
|
|
356
|
+
event_ids=event_ids,
|
|
357
|
+
)
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
##### fetch_event_documents
|
|
361
|
+
|
|
362
|
+
```python
|
|
363
|
+
def fetch_event_documents(
|
|
364
|
+
self,
|
|
365
|
+
event_ids: list[int],
|
|
366
|
+
document_ids: list[int],
|
|
367
|
+
limit: int = 500,
|
|
368
|
+
max_iteration: int = 20,
|
|
369
|
+
) -> DocumentResults:
|
|
370
|
+
"""
|
|
371
|
+
Retrieve documents for a list of events.
|
|
372
|
+
|
|
373
|
+
Args:
|
|
374
|
+
event_ids: List of event IDs
|
|
375
|
+
document_ids: List of document type IDs to filter
|
|
376
|
+
limit: Items per request (max 500)
|
|
377
|
+
max_iteration: Maximum number of pagination iterations
|
|
378
|
+
|
|
379
|
+
Returns:
|
|
380
|
+
DocumentResults object with .data containing list of DocumentDto objects
|
|
381
|
+
"""
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
##### Static Methods
|
|
385
|
+
|
|
386
|
+
```python
|
|
387
|
+
@staticmethod
|
|
388
|
+
def get_event_subtype_ids_from_event_types(
|
|
389
|
+
event_types: list[EventType],
|
|
390
|
+
) -> list[int]:
|
|
391
|
+
"""
|
|
392
|
+
Convert EventType enums to Quartr API event subtype IDs.
|
|
393
|
+
|
|
394
|
+
Args:
|
|
395
|
+
event_types: List of EventType enums
|
|
396
|
+
|
|
397
|
+
Returns:
|
|
398
|
+
List of event subtype IDs
|
|
399
|
+
"""
|
|
400
|
+
|
|
401
|
+
@staticmethod
|
|
402
|
+
def get_document_ids_from_document_types(
|
|
403
|
+
document_types: list[DocumentType],
|
|
404
|
+
) -> list[int]:
|
|
405
|
+
"""
|
|
406
|
+
Convert DocumentType enums to Quartr API document type IDs.
|
|
407
|
+
|
|
408
|
+
Args:
|
|
409
|
+
document_types: List of DocumentType enums
|
|
410
|
+
|
|
411
|
+
Returns:
|
|
412
|
+
List of document type IDs
|
|
413
|
+
"""
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
## Response Models
|
|
417
|
+
|
|
418
|
+
### EventResults
|
|
419
|
+
|
|
420
|
+
Wrapper object returned by `fetch_company_events`:
|
|
421
|
+
|
|
422
|
+
```python
|
|
423
|
+
class EventResults:
|
|
424
|
+
data: list[EventDto] # Access events via .data attribute
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
### EventDto
|
|
428
|
+
|
|
429
|
+
```python
|
|
430
|
+
class EventDto:
|
|
431
|
+
company_id: float
|
|
432
|
+
date: datetime
|
|
433
|
+
id: float
|
|
434
|
+
title: str
|
|
435
|
+
type_id: float
|
|
436
|
+
fiscal_year: float | None
|
|
437
|
+
fiscal_period: str | None
|
|
438
|
+
backlink_url: str
|
|
439
|
+
updated_at: datetime
|
|
440
|
+
created_at: datetime
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
### DocumentResults
|
|
444
|
+
|
|
445
|
+
Wrapper object returned by `fetch_event_documents`:
|
|
446
|
+
|
|
447
|
+
```python
|
|
448
|
+
class DocumentResults:
|
|
449
|
+
data: list[DocumentDto] # Access documents via .data attribute
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
### DocumentDto
|
|
453
|
+
|
|
454
|
+
```python
|
|
455
|
+
class DocumentDto:
|
|
456
|
+
company_id: float | None
|
|
457
|
+
event_id: float | None
|
|
458
|
+
file_url: str
|
|
459
|
+
id: float
|
|
460
|
+
type_id: float
|
|
461
|
+
updated_at: datetime
|
|
462
|
+
created_at: datetime
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
### QuartrEarningsCallTranscript
|
|
466
|
+
|
|
467
|
+
Complete earnings call transcript with speaker mapping:
|
|
468
|
+
|
|
469
|
+
```python
|
|
470
|
+
class QuartrEarningsCallTranscript:
|
|
471
|
+
version: str
|
|
472
|
+
event_id: int
|
|
473
|
+
company_id: int
|
|
474
|
+
transcript: Transcript
|
|
475
|
+
speaker_mapping: list[SpeakerMapping]
|
|
476
|
+
|
|
477
|
+
# Methods
|
|
478
|
+
def to_markdown(self) -> str
|
|
479
|
+
@classmethod
|
|
480
|
+
def from_quartr_transcript_url(cls, url: str) -> Self
|
|
481
|
+
@classmethod
|
|
482
|
+
async def from_quartr_transcript_url_async(cls, url: str) -> Self
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
## Testing
|
|
486
|
+
|
|
487
|
+
Run the test suite:
|
|
488
|
+
|
|
489
|
+
```bash
|
|
490
|
+
poetry run pytest
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
Run with coverage:
|
|
494
|
+
|
|
495
|
+
```bash
|
|
496
|
+
poetry run pytest --cov=unique_quartr --cov-report=html
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
Run specific test files:
|
|
500
|
+
|
|
501
|
+
```bash
|
|
502
|
+
poetry run pytest tests/test_service.py
|
|
503
|
+
poetry run pytest tests/test_constants.py
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
## Error Handling
|
|
507
|
+
|
|
508
|
+
The library will raise exceptions in the following cases:
|
|
509
|
+
|
|
510
|
+
- **Missing API Credentials**: `ValueError` when `QUARTR_API_CREDS` is not set
|
|
511
|
+
- **Company Not Activated**: `ValueError` when the company_id is not in `QUARTR_API_ACTIVATED_COMPANIES`
|
|
512
|
+
- **API Errors**: Various HTTP errors from the Quartr API
|
|
513
|
+
|
|
514
|
+
### Example Error Handling
|
|
515
|
+
|
|
516
|
+
```python
|
|
517
|
+
from unique_quartr.service import QuartrService
|
|
518
|
+
|
|
519
|
+
try:
|
|
520
|
+
service = QuartrService(
|
|
521
|
+
company_id="invalid_company",
|
|
522
|
+
requestor_type=RequestorType.SYNC,
|
|
523
|
+
)
|
|
524
|
+
except ValueError as e:
|
|
525
|
+
print(f"Configuration error: {e}")
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
## Development
|
|
529
|
+
|
|
530
|
+
### Setup Development Environment
|
|
531
|
+
|
|
532
|
+
```bash
|
|
533
|
+
# Clone the repository
|
|
534
|
+
git clone <repository_url>
|
|
535
|
+
cd unique_quartr
|
|
536
|
+
|
|
537
|
+
# Install dependencies
|
|
538
|
+
poetry install
|
|
539
|
+
|
|
540
|
+
# Run linting
|
|
541
|
+
poetry run ruff check .
|
|
542
|
+
|
|
543
|
+
# Run formatting
|
|
544
|
+
poetry run ruff format .
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
### Project Structure
|
|
548
|
+
|
|
549
|
+
```
|
|
550
|
+
unique_quartr/
|
|
551
|
+
├── constants/
|
|
552
|
+
│ ├── document_types.py # Document type enums and mappings
|
|
553
|
+
│ └── event_types.py # Event type enums and mappings
|
|
554
|
+
├── endpoints/
|
|
555
|
+
│ ├── api.py # API endpoint definitions
|
|
556
|
+
│ └── schemas.py # Pydantic models for API requests/responses
|
|
557
|
+
├── transcripts/
|
|
558
|
+
│ └── earnings_call/
|
|
559
|
+
│ ├── __init__.py # Transcript module exports
|
|
560
|
+
│ ├── schema.py # Transcript data models
|
|
561
|
+
│ └── transcript_template.j2 # Jinja2 template for markdown export
|
|
562
|
+
├── service.py # Main service class
|
|
563
|
+
└── settings.py # Configuration and settings
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
## License
|
|
567
|
+
|
|
568
|
+
Proprietary
|
|
569
|
+
|
|
570
|
+
## Authors
|
|
571
|
+
|
|
572
|
+
- Rami Azouz <rami.ext@unique.ch>
|
|
573
|
+
|
|
574
|
+
## Support
|
|
575
|
+
|
|
576
|
+
For issues and questions, please contact the maintainers or refer to the [Quartr API documentation](https://quartr.dev/api-reference).
|