Skip to content

Commit 771668c

Browse files
committed
Deleted async_learn.py
Deleted example_async_simple.py Updated async_call_nb.ipynb to add more details. Updated sync_call_nb.ipynb to add more details. Updated example_async_gather.py code flow. Updated example_client.py code flow. Updated example_sync_httpx.py code flow.
1 parent c44c78b commit 771668c

8 files changed

Lines changed: 407 additions & 535 deletions

README.md

Lines changed: 90 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,94 @@
77

88
Python examples that use [`httpx`](https://www.python-httpx.org/) to authenticate with [LSEG Data Platform APIs](https://developers.lseg.com/en/api-catalog/refinitiv-data-platform/refinitiv-data-platform-apis) (RDP, also known as Delivery Platform) using OAuth 2.0 Password Grant, then call sample REST endpoints — covering both synchronous and asynchronous patterns.
99

10+
## What is Data Platform APIs?
11+
12+
[LSEG Data Platform](https://developers.lseg.com/en/api-catalog/refinitiv-data-platform/refinitiv-data-platform-apis) (RDP APIs, also known as Delivery Platform in LSEG Real-Time) provides simple web based API access to a broad range of LSEG content.
13+
14+
RDP APIs give developers seamless and holistic access to all of the LSEG content such as Historical Pricing, Environmental Social and Governance (ESG), News, Research, etc, and commingled with their content, enriching, integrating, and distributing the data through a single interface, delivered wherever they need it. The RDP APIs delivery mechanisms are the following:
15+
* Request - Response: RESTful web service (HTTP GET, POST, PUT or DELETE)
16+
* Alert: delivery is a mechanism to receive asynchronous updates (alerts) to a subscription.
17+
* Bulks: deliver substantial payloads, like the end-of-day pricing data for the whole venue.
18+
* Streaming: deliver real-time delivery of messages.
19+
20+
This example project is focusing on the Request-Response: RESTful web service delivery method only.
21+
22+
For more detail regarding the Data Platform, please see the following APIs resources:
23+
- [Quick Start](https://developers.lseg.com/en/api-catalog/refinitiv-data-platform/refinitiv-data-platform-apis/quick-start) page.
24+
- [Tutorials](https://developers.lseg.com/en/api-catalog/refinitiv-data-platform/refinitiv-data-platform-apis/tutorials) page.
25+
- [RDP APIs: Introduction to the Request-Response API](https://developers.lseg.com/en/api-catalog/refinitiv-data-platform/refinitiv-data-platform-apis/tutorials#introduction-to-the-request-response-api) page.
26+
27+
## What is HTTPX?
28+
29+
[HTTPX](https://www.python-httpx.org/) is a full featured modern HTTP client for Python 3. It provides a set of synchronous and modern asynchronous APIs with [HTTP/2](https://httpwg.org/specs/rfc7540.html) supported. Any Python developers who are using the [Requests](https://requests.readthedocs.io/en/latest/) library can migrate to the HTTPX library easily with their [requests-compatibility API interfaces](https://www.python-httpx.org/compatibility/) like the following examples:
30+
31+
**HTTP GET**
32+
33+
```python
34+
import httpx
35+
36+
params = {'key1': 'value1', 'key2': 'value2'}
37+
r = httpx.get('https://httpbin.org/get', params=params)
38+
r.raise_for_status()
39+
print(r.json())
40+
```
41+
42+
**HTTP POST**
43+
44+
```python
45+
import httpx
46+
47+
data = {'integer': 123, 'boolean': True, 'list': ['a', 'b', 'c']}
48+
r = httpx.post('https://httpbin.org/post', json=data)
49+
r.raise_for_status()
50+
print(r.json())
51+
```
52+
53+
HTTPX also provides [`httpx.Client`](https://www.python-httpx.org/advanced/clients/) object (equivalent to [`requests.Session()`](https://requests.readthedocs.io/en/latest/user/advanced/#session-objects) object in the [Requests library](https://requests.readthedocs.io/en/latest/)) as synchronous HTTP client for developers.
54+
55+
Example:
56+
57+
```python
58+
import httpx
59+
60+
with httpx.Client(base_url='http://httpbin.org') as client:
61+
r = client.get('/get')
62+
r.raise_for_status()
63+
print(r.status_code)
64+
```
65+
66+
The asynchronous execute model examples, the library offers [`httpx.AsyncClient`](https://www.python-httpx.org/api/#asyncclient) as an asynchronous HTTP client to use with Python asynchronous library such as a [built-in asyncio](https://docs.python.org/3/library/asyncio.html), [Trio](https://trio.readthedocs.io/en/stable/), and [AnyIO](https://anyio.readthedocs.io/en/stable/) libraries. I am demonstrating with asyncio in this project.
67+
68+
Example:
69+
70+
```python
71+
import asyncio
72+
import httpx
73+
74+
async def main():
75+
async with httpx.AsyncClient() as client:
76+
response = await client.get('https://www.example.com/')
77+
print(response)
78+
79+
asyncio.run(main())
80+
```
81+
1082
## Project Structure
1183

1284
```
1385
├── requirements.txt # Pinned dependencies
1486
src/
1587
├── .env.example # Environment variable template
16-
├── simple_call_nb.ipynb # Jupyter notebook — synchronous, shared httpx.Client
88+
├── sync_call_nb.ipynb # Jupyter notebook — synchronous, shared httpx.Client
1789
├── async_call_nb.ipynb # Jupyter notebook — async, asyncio.gather() with Semaphore
1890
├── example_sync_httpx.py # Synchronous — direct httpx module calls (no shared client)
1991
├── example_client.py # Synchronous — shared httpx.Client
20-
├── example_async_simple.py # Async — sequential awaits in a loop
21-
├── example_async_gather.py # Async — asyncio.gather() with Semaphore
22-
├── example_async_taskgroup.py # Async — asyncio.TaskGroup with Semaphore
23-
└── async_learn.py # Learning script — ExceptionGroup / except*
92+
└── example_async_gather.py # Async — asyncio.gather() with Semaphore
2493
```
2594

2695
## Included Notebook
2796

28-
### `src/simple_call_nb.ipynb` — Synchronous, step-by-step Jupyter notebook
97+
### `src/sync_call_nb.ipynb` — Synchronous, step-by-step Jupyter notebook
2998

3099
Interactive notebook version of the synchronous workflow. Each logical step is a separate cell with a markdown explanation above it, making it easy to run and inspect results incrementally.
31100

@@ -67,17 +136,16 @@ Notebook structure:
67136

68137
## Included Scripts
69138

70-
### `src/example_sync_httpx.py`Synchronous, direct `httpx` calls
139+
### `src/example_async_gather.py`Async with `asyncio.gather()` and `Semaphore`
71140

72-
Simplest synchronous example. Each function calls `httpx.get()` / `httpx.post()` directly — no shared client or connection pool. Good as a minimal reference or quick script.
141+
Async script that fires all RIC requests concurrently via `asyncio.gather()`, with an `asyncio.Semaphore` to cap the number of in-flight requests and avoid hitting server rate limits.
73142

74143
Demonstrates:
75-
- `POST /auth/oauth2/v1/token` — OAuth 2.0 Password Grant authentication
76-
- `GET /data/pricing/chains/v1/` — chain constituent lookup for a single RIC
77-
- `POST /data/historical-pricing/v1/views/events` — historical trade events for multiple RICs
78-
- Refresh token flow (`grant_type=refresh_token`)
79-
- `POST /auth/oauth2/v1/revoke` — session revocation using HTTP Basic Auth
80-
- Per-call `verify=False` passed directly to each `httpx` function
144+
- `POST /auth/oauth2/v1/token` — async authentication
145+
- `GET /data/historical-pricing/v1/views/interday-summaries/{ric}` — concurrent fetches for 10 RICs
146+
- `asyncio.Semaphore` — limits concurrent requests (default: 3)
147+
- `return_exceptions=True` — prevents one failure from cancelling the rest; each result is inspected individually
148+
- Per-result error handling: `httpx.HTTPStatusError`, `httpx.RequestError`, generic `Exception`
81149

82150
### `src/example_client.py` — Synchronous with shared client
83151

@@ -91,30 +159,17 @@ Demonstrates:
91159
- `POST /auth/oauth2/v1/revoke` — session revocation — commented out, ready to enable
92160
- Environment validation with a `_require_env()` helper that fails fast on missing credentials
93161

94-
### `src/example_async_simple.py` — Async, sequential loop
95-
96-
Async script using `httpx.AsyncClient`. Fetches interday-summaries for each RIC one after another inside a `for` loop. Simple starting point before introducing concurrency.
97-
98-
Demonstrates:
99-
- `POST /auth/oauth2/v1/token` — async authentication
100-
- `GET /data/historical-pricing/v1/views/interday-summaries/{ric}` — daily OHLCV data with corporate-action adjustments
101-
- Sequential `await` per RIC — no concurrent requests
102-
103-
### `src/example_async_gather.py` — Async with `asyncio.gather()` and `Semaphore`
162+
### `src/example_sync_httpx.py` — Synchronous, direct `httpx` calls
104163

105-
Async script that fires all RIC requests concurrently via `asyncio.gather()`, with an `asyncio.Semaphore` to cap the number of in-flight requests and avoid hitting server rate limits.
164+
Simplest synchronous example. Each function calls `httpx.get()` / `httpx.post()` directly — no shared client or connection pool. Good as a minimal reference or quick script.
106165

107166
Demonstrates:
108-
- `POST /auth/oauth2/v1/token` — async authentication
109-
- `GET /data/historical-pricing/v1/views/interday-summaries/{ric}` — concurrent fetches for 10 RICs
110-
- `asyncio.Semaphore` — limits concurrent requests (default: 3)
111-
- `return_exceptions=True` — prevents one failure from cancelling the rest; each result is inspected individually
112-
- Per-result error handling: `httpx.HTTPStatusError`, `httpx.RequestError`, generic `Exception`
113-
114-
115-
### `src/async_learn.py``ExceptionGroup` and `except*` sandbox
116-
117-
Standalone learning script demonstrating how `asyncio.gather(return_exceptions=True)` results can be re-raised as an `ExceptionGroup`, and how `except*` dispatches individual exception types from the group.
167+
- `POST /auth/oauth2/v1/token` — OAuth 2.0 Password Grant authentication
168+
- `GET /data/pricing/chains/v1/` — chain constituent lookup for a single RIC
169+
- `POST /data/historical-pricing/v1/views/events` — historical trade events for multiple RICs
170+
- Refresh token flow (`grant_type=refresh_token`)
171+
- `POST /auth/oauth2/v1/revoke` — session revocation using HTTP Basic Auth
172+
- Per-call `verify=False` passed directly to each `httpx` function
118173

119174
## Prerequisites
120175

@@ -163,14 +218,8 @@ jupyter lab src/async_call_nb.ipynb
163218
# Synchronous
164219
python .\src\example_client.py
165220
166-
# Async — sequential loop
167-
python .\src\example_async_simple.py
168-
169221
# Async — concurrent via asyncio.gather()
170222
python .\src\example_async_gather.py
171-
172-
# Async — concurrent via asyncio.TaskGroup
173-
python .\src\example_async_taskgroup.py
174223
```
175224

176225
Each script prints the authenticated request URLs and JSON responses. Timing is printed on exit for the async scripts.

0 commit comments

Comments
 (0)