Skip to content

Commit

Permalink
define interfaces
Browse files Browse the repository at this point in the history
  • Loading branch information
patrick-zippenfenig committed Oct 17, 2023
1 parent 03d0636 commit ea6b382
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 25 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ __pycache__/
# C extensions
*.so

test.py
.cache.sqlite

# Distribution / packaging
.Python
build/
Expand Down
20 changes: 20 additions & 0 deletions DEVELOPMENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
### Development

Install dependencies

```bash
pip3 install .
pip3 install ".[test]"
pip3 install pytest-xdist
pre-commit install
```

Run linter and tests
```bash
black .
flake8
bandit -r openmeteo_requests/
pylint openmeteo_requests/
python3 -m pytest tests/
pre-commit run --all-files
```
94 changes: 80 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,87 @@
# python-requests
Open-Meteo Python Library using `requests`
# Open-Meteo Python API Client

An API client to get weather data from the Open-Meteo Weather API based on the Python library `requests`.

Instead of using JSON, the API client uses FlatBuffers to transfer data. Encoding data in FlatBuffers is more efficient for long time-series data. Data can be transferred to `numpy` or `pandas` using [Zero-Copy](https://en.wikipedia.org/wiki/Zero-copy) to analyze large amount of data quickly.

TODO:
- Document data structure
- Consider dedicated pandas library

### Development
## Basic Usage

```bash
pip3 install .
pip3 install ".[test]"
pip3 install pytest-xdist
pre-commit install
```python
# pip install openmeteo-requests

black .
flake8
bandit -r openmeteo_requests/
pylint openmeteo_requests/
python3 -m pytest tests/
pre-commit run --all-files
import openmeteo_requests

om = openmeteo_requests.Client()
params = {
"latitude": 52.54,
"longitude": 13.41,
"hourly": ["temperature_2m", "precipitation"],
"current": ["temperature_2m"]
}

results = om.weather_api("https://api.open-meteo.com/v1/forecast", params=params)
result = results[0]

print(f"Coordinates {result.Latitude()}°E {result.Longitude()}°N {result.Elevation()} m asl")
print(f"Timezone {result.Timezone()} {result.TimezoneAbbreviation()} Offset={result.UtcOffsetSeconds()}s")

print(f"Current temperature is {result.Current().Temperature2m().Value() °C}")

# Accessing hourly forecasts as numpy arrays
hourly = result.Hourly()
temperature_2m = hourly.Temperature2m().ValuesAsNumpy()
precipitation = hourly.Temperature2m().ValuesAsNumpy()

# Usage with Pandas Dataframes
import pandas as pd
date = pd.date_range(
start=pd.to_datetime(hourly.Time().Start(), unit="s"),
end=pd.to_datetime(hourly.Time().End(), unit="s"),
freq=pd.Timedelta(seconds=hourly.Time().Interval()),
inclusive="left"
)
df = pd.DataFrame(
data={
"date": date,
"temperature_2m": hourly.Temperature2m().ValuesAsNumpy(),
"precipitation": hourly.Precipitation().ValuesAsNumpy()
}
)
print(df)
#date temperature_2m precipitation
#0 2023-08-01 00:00:00 16.945999 1.7
#1 2023-08-01 01:00:00 16.996000 2.1
#2 2023-08-01 02:00:00 16.996000 1.0
#3 2023-08-01 03:00:00 16.846001 0.2
```

## Caching Data

If you are working with large amounts of data, caching data can make it easier to develop. You can pass a cached session from the library `requests-cache` to the Open-Meteo API client.

The following example stores all data indefinitely (`expire_after=-1`) in a SQLite database called `.cache.sqlite`. For more options read the [requests-cache documentation](https://pypi.org/project/requests-cache/).

Additionally, `retry-requests` to automatically retry failed API calls in case there has been any unexpected network or server error.

```python
# pip install openmeteo-requests
# pip install requests-cache retry-requests

import openmeteo_requests
import requests_cache
from retry_requests import retry

# Setup the Open-Meteo API client with a cache and retry mechanism
cache_session = requests_cache.CachedSession('.cache', expire_after=-1)
retry_session = retry(cache_session, retries=5, backoff_factor=0.2)
om = openmeteo_requests.Client(session=retry_session)

# Using the client object `om` will now cache all weather data
```

# License
MIT
5 changes: 5 additions & 0 deletions openmeteo_requests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from __future__ import annotations

from openmeteo_requests.Client import Client

__all__ = ['Client']
24 changes: 13 additions & 11 deletions tests/test_methods.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@

import pytest

from openmeteo_requests.Client import Client
import openmeteo_requests


def test_fetch_all():
om = Client()
om = openmeteo_requests.Client()
params = {
"latitude": [52.54, 48.1, 48.4],
"longitude": [13.41, 9.31, 8.5],
Expand All @@ -21,15 +21,17 @@ def test_fetch_all():

results = om.weather_api("https://archive-api.open-meteo.com/v1/archive", params=params)
assert len(results) == 3
res = results[0]
assert res.Latitude() == pytest.approx(52.5)
assert res.Longitude() == pytest.approx(13.4)
res = results[1]
assert res.Latitude() == pytest.approx(48.1)
assert res.Longitude() == pytest.approx(9.3)
print("Coordinates ", res.Latitude(), res.Longitude(), res.Elevation())
print(res.Timezone(), res.TimezoneAbbreviation())
print("Generation time", res.GenerationtimeMs())
result = results[0]
assert result.Latitude() == pytest.approx(52.5)
assert result.Longitude() == pytest.approx(13.4)
result = results[1]
assert result.Latitude() == pytest.approx(48.1)
assert result.Longitude() == pytest.approx(9.3)
result = results[0]

print(f"Coordinates {result.Latitude()}°E {result.Longitude()}°N {result.Elevation()} m asl")
print(f"Timezone {result.Timezone()} {result.TimezoneAbbreviation()} {result.UtcOffsetSeconds()}")
print(f"Generation time {result.GenerationtimeMs()} ms")


def test_int_client():
Expand Down

0 comments on commit ea6b382

Please sign in to comment.