eolas-data 1.2.0__tar.gz → 1.3.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.
- {eolas_data-1.2.0 → eolas_data-1.3.0}/PKG-INFO +11 -9
- {eolas_data-1.2.0 → eolas_data-1.3.0}/README.md +9 -5
- {eolas_data-1.2.0 → eolas_data-1.3.0}/eolas_data/cli.py +25 -3
- {eolas_data-1.2.0 → eolas_data-1.3.0}/eolas_data/client.py +8 -2
- eolas_data-1.3.0/eolas_data/dataset.py +46 -0
- {eolas_data-1.2.0 → eolas_data-1.3.0}/pyproject.toml +2 -3
- eolas_data-1.2.0/eolas_data/dataset.py +0 -66
- {eolas_data-1.2.0 → eolas_data-1.3.0}/.github/workflows/catalog-drift.yml +0 -0
- {eolas_data-1.2.0 → eolas_data-1.3.0}/.github/workflows/publish.yml +0 -0
- {eolas_data-1.2.0 → eolas_data-1.3.0}/.gitignore +0 -0
- {eolas_data-1.2.0 → eolas_data-1.3.0}/eolas_data/__init__.py +0 -0
- {eolas_data-1.2.0 → eolas_data-1.3.0}/eolas_data/_dataset_names.py +0 -0
- {eolas_data-1.2.0 → eolas_data-1.3.0}/eolas_data/_regen_names.py +0 -0
- {eolas_data-1.2.0 → eolas_data-1.3.0}/eolas_data/exceptions.py +0 -0
- {eolas_data-1.2.0 → eolas_data-1.3.0}/eolas_data/schedule.py +0 -0
- {eolas_data-1.2.0 → eolas_data-1.3.0}/tests/test_cli.py +0 -0
- {eolas_data-1.2.0 → eolas_data-1.3.0}/tests/test_client.py +0 -0
- {eolas_data-1.2.0 → eolas_data-1.3.0}/tests/test_schedule.py +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: eolas-data
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
4
4
|
Summary: Python client for the eolas.fyi statistical data API (NZ, Australia, OECD)
|
|
5
5
|
Project-URL: Homepage, https://eolas.fyi
|
|
6
|
-
Project-URL: Documentation, https://
|
|
6
|
+
Project-URL: Documentation, https://docs.eolas.fyi/
|
|
7
7
|
Project-URL: Repository, https://github.com/phildonovan/eolas-data
|
|
8
8
|
Project-URL: Bug Tracker, https://github.com/phildonovan/eolas-data/issues
|
|
9
9
|
Author-email: Virtus Solutions <phil@virtus-solutions.io>
|
|
@@ -36,8 +36,6 @@ Requires-Dist: typer>=0.12; extra == 'dev'
|
|
|
36
36
|
Provides-Extra: geo
|
|
37
37
|
Requires-Dist: geopandas>=0.14; extra == 'geo'
|
|
38
38
|
Requires-Dist: shapely>=2.0; extra == 'geo'
|
|
39
|
-
Provides-Extra: plot
|
|
40
|
-
Requires-Dist: matplotlib>=3.5; extra == 'plot'
|
|
41
39
|
Provides-Extra: polars
|
|
42
40
|
Requires-Dist: polars>=0.20; extra == 'polars'
|
|
43
41
|
Description-Content-Type: text/markdown
|
|
@@ -168,13 +166,17 @@ df = client.get("nz_cpi", engine="polars")
|
|
|
168
166
|
|
|
169
167
|
## Plotting
|
|
170
168
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
169
|
+
`Dataset` is a `pandas.DataFrame` subclass — use matplotlib / seaborn / plotly
|
|
170
|
+
directly. No bundled plot helper, because there's no universal "right" plot for
|
|
171
|
+
a tidy dataset (single-series time series vs. wide multi-measure vs. WKT
|
|
172
|
+
geometry all need different code).
|
|
174
173
|
|
|
175
174
|
```python
|
|
175
|
+
import matplotlib.pyplot as plt
|
|
176
|
+
|
|
176
177
|
df = client.statsnz("nz_cpi")
|
|
177
|
-
df.
|
|
178
|
+
df.plot(x="date", y="value")
|
|
179
|
+
plt.show()
|
|
178
180
|
```
|
|
179
181
|
|
|
180
182
|
## Type stubs
|
|
@@ -198,7 +200,7 @@ The previous package name was `vswarehouse`. Direct equivalents:
|
|
|
198
200
|
|---|---|
|
|
199
201
|
| `from vswarehouse import Client, VSeries` | `from eolas_data import Client, Dataset` |
|
|
200
202
|
| `df.vs_name`, `df.vs_source` | `df.eolas_name`, `df.eolas_source` |
|
|
201
|
-
| `df.plot_series()` | `df.
|
|
203
|
+
| `df.plot_series()` | *(removed in v1.3.0 — use `df.plot(x="date", y="value")` directly; the helper silently mis-rendered datasets with multi-row dates)* |
|
|
202
204
|
| `VS_API_KEY` env var | `EOLAS_API_KEY` (legacy `VS_API_KEY` still honoured) |
|
|
203
205
|
|
|
204
206
|
The API surface is otherwise identical. The default base URL is now `https://api.eolas.fyi` (the old `https://api.virtus-solutions.io` still 301-redirects and works fine — but uses the legacy endpoint shape).
|
|
@@ -124,13 +124,17 @@ df = client.get("nz_cpi", engine="polars")
|
|
|
124
124
|
|
|
125
125
|
## Plotting
|
|
126
126
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
127
|
+
`Dataset` is a `pandas.DataFrame` subclass — use matplotlib / seaborn / plotly
|
|
128
|
+
directly. No bundled plot helper, because there's no universal "right" plot for
|
|
129
|
+
a tidy dataset (single-series time series vs. wide multi-measure vs. WKT
|
|
130
|
+
geometry all need different code).
|
|
130
131
|
|
|
131
132
|
```python
|
|
133
|
+
import matplotlib.pyplot as plt
|
|
134
|
+
|
|
132
135
|
df = client.statsnz("nz_cpi")
|
|
133
|
-
df.
|
|
136
|
+
df.plot(x="date", y="value")
|
|
137
|
+
plt.show()
|
|
134
138
|
```
|
|
135
139
|
|
|
136
140
|
## Type stubs
|
|
@@ -154,7 +158,7 @@ The previous package name was `vswarehouse`. Direct equivalents:
|
|
|
154
158
|
|---|---|
|
|
155
159
|
| `from vswarehouse import Client, VSeries` | `from eolas_data import Client, Dataset` |
|
|
156
160
|
| `df.vs_name`, `df.vs_source` | `df.eolas_name`, `df.eolas_source` |
|
|
157
|
-
| `df.plot_series()` | `df.
|
|
161
|
+
| `df.plot_series()` | *(removed in v1.3.0 — use `df.plot(x="date", y="value")` directly; the helper silently mis-rendered datasets with multi-row dates)* |
|
|
158
162
|
| `VS_API_KEY` env var | `EOLAS_API_KEY` (legacy `VS_API_KEY` still honoured) |
|
|
159
163
|
|
|
160
164
|
The API surface is otherwise identical. The default base URL is now `https://api.eolas.fyi` (the old `https://api.virtus-solutions.io` still 301-redirects and works fine — but uses the legacy endpoint shape).
|
|
@@ -580,7 +580,7 @@ def integrate_meltano(
|
|
|
580
580
|
json_out: bool = typer.Option(False, "--json"),
|
|
581
581
|
api_key: Optional[str] = typer.Option(None, "--api-key"),
|
|
582
582
|
) -> None:
|
|
583
|
-
"""Generate a Meltano project (uses `tap-rest-api-msdk`) for the chosen datasets."""
|
|
583
|
+
"""[verified] Generate a Meltano project (uses `tap-rest-api-msdk`) for the chosen datasets."""
|
|
584
584
|
_run_integration("meltano", datasets, output or _default_output_dir("meltano"),
|
|
585
585
|
force, api_key, json_out)
|
|
586
586
|
|
|
@@ -593,9 +593,20 @@ def integrate_fivetran(
|
|
|
593
593
|
json_out: bool = typer.Option(False, "--json"),
|
|
594
594
|
api_key: Optional[str] = typer.Option(None, "--api-key"),
|
|
595
595
|
) -> None:
|
|
596
|
-
"""Generate a Fivetran Connector Builder YAML for the chosen datasets.
|
|
596
|
+
"""[experimental] Generate a Fivetran Connector Builder YAML for the chosen datasets.
|
|
597
|
+
|
|
598
|
+
Output is structure-verified (parses as YAML, has all the fields the spec
|
|
599
|
+
documents) but has not yet been end-to-end tested against a real Fivetran
|
|
600
|
+
Connector Builder import. If the import rejects with a schema error,
|
|
601
|
+
please share the error so the generator can be fixed.
|
|
602
|
+
"""
|
|
597
603
|
_run_integration("fivetran", datasets, output or _default_output_dir("fivetran"),
|
|
598
604
|
force, api_key, json_out)
|
|
605
|
+
if not _machine_mode(json_out):
|
|
606
|
+
err_console.print(
|
|
607
|
+
"[yellow]experimental:[/yellow] Fivetran output is structure-verified "
|
|
608
|
+
"but not yet end-to-end tested against a real account."
|
|
609
|
+
)
|
|
599
610
|
|
|
600
611
|
|
|
601
612
|
@integrate_app.command("azure-data-factory")
|
|
@@ -606,10 +617,21 @@ def integrate_adf(
|
|
|
606
617
|
json_out: bool = typer.Option(False, "--json"),
|
|
607
618
|
api_key: Optional[str] = typer.Option(None, "--api-key"),
|
|
608
619
|
) -> None:
|
|
609
|
-
"""Generate Azure Data Factory linked-service / dataset / pipeline JSON.
|
|
620
|
+
"""[experimental] Generate Azure Data Factory linked-service / dataset / pipeline JSON.
|
|
621
|
+
|
|
622
|
+
Output is structure-verified (linked-service references resolve, datasets
|
|
623
|
+
reference real linked services, pipeline activities reference real
|
|
624
|
+
datasets) but has not yet been end-to-end tested against a real Azure
|
|
625
|
+
subscription.
|
|
626
|
+
"""
|
|
610
627
|
_run_integration("azure-data-factory", datasets,
|
|
611
628
|
output or _default_output_dir("adf"),
|
|
612
629
|
force, api_key, json_out)
|
|
630
|
+
if not _machine_mode(json_out):
|
|
631
|
+
err_console.print(
|
|
632
|
+
"[yellow]experimental:[/yellow] Azure Data Factory output is "
|
|
633
|
+
"structure-verified but not yet end-to-end tested against a real subscription."
|
|
634
|
+
)
|
|
613
635
|
|
|
614
636
|
|
|
615
637
|
# Allow `python -m eolas_data.cli`
|
|
@@ -166,8 +166,14 @@ class Client:
|
|
|
166
166
|
return self._get_source(name, "LINZ", **kwargs)
|
|
167
167
|
|
|
168
168
|
def statsnz_geo(self, name, **kwargs) -> Dataset:
|
|
169
|
-
"""Fetch a Stats NZ
|
|
170
|
-
|
|
169
|
+
"""Fetch a Stats NZ geospatial dataset (boundaries, census meshblocks, etc.).
|
|
170
|
+
|
|
171
|
+
Kept as a convenience helper for discoverability — the server returns
|
|
172
|
+
``source = "Stats NZ"`` for both SDMX time series and Datafinder
|
|
173
|
+
geospatial datasets, so the metadata on the returned Dataset reads
|
|
174
|
+
``"Stats NZ"`` (not ``"Stats NZ Geospatial"``).
|
|
175
|
+
"""
|
|
176
|
+
return self._get_source(name, "Stats NZ", **kwargs)
|
|
171
177
|
|
|
172
178
|
def mbie(self, name, **kwargs) -> Dataset:
|
|
173
179
|
"""Fetch an MBIE dataset."""
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import pandas as pd
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Dataset(pd.DataFrame):
|
|
7
|
+
"""A pandas DataFrame with eolas dataset metadata.
|
|
8
|
+
|
|
9
|
+
Behaves exactly like a DataFrame — all pandas operations work normally.
|
|
10
|
+
Extra attributes:
|
|
11
|
+
eolas_name: Dataset identifier (e.g. ``"nz_cpi"``).
|
|
12
|
+
eolas_source: Data source label (e.g. ``"Stats NZ"``).
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
_metadata = ["eolas_name", "eolas_source"]
|
|
16
|
+
|
|
17
|
+
@property
|
|
18
|
+
def _constructor(self):
|
|
19
|
+
return Dataset
|
|
20
|
+
|
|
21
|
+
def __repr__(self) -> str:
|
|
22
|
+
name = getattr(self, "eolas_name", "") or ""
|
|
23
|
+
source = getattr(self, "eolas_source", "") or ""
|
|
24
|
+
if name:
|
|
25
|
+
header = f"# Dataset: {name}"
|
|
26
|
+
if source:
|
|
27
|
+
header += f" [{source}]"
|
|
28
|
+
header += f"\n# {len(self)} rows\n"
|
|
29
|
+
return header + pd.DataFrame.__repr__(self)
|
|
30
|
+
return pd.DataFrame.__repr__(self)
|
|
31
|
+
|
|
32
|
+
# ------------------------------------------------------------------
|
|
33
|
+
# plot_dataset() was removed in v1.3.0.
|
|
34
|
+
#
|
|
35
|
+
# It auto-picked `date` and `value` columns and drew a single matplotlib
|
|
36
|
+
# line — but datasets with a dimension column (multiple series per date)
|
|
37
|
+
# produced silent zigzag traces. Rather than ship a helper that has to
|
|
38
|
+
# know each dataset's shape, plotting is now the caller's responsibility.
|
|
39
|
+
# `Dataset` subclasses `DataFrame`, so any matplotlib / seaborn / plotly
|
|
40
|
+
# workflow works straight out of the box:
|
|
41
|
+
#
|
|
42
|
+
# import matplotlib.pyplot as plt
|
|
43
|
+
# df.plot(x="date", y="value")
|
|
44
|
+
#
|
|
45
|
+
# See README for one-liners.
|
|
46
|
+
# ------------------------------------------------------------------
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "eolas-data"
|
|
7
|
-
version = "1.
|
|
7
|
+
version = "1.3.0"
|
|
8
8
|
description = "Python client for the eolas.fyi statistical data API (NZ, Australia, OECD)"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "MIT" }
|
|
@@ -30,14 +30,13 @@ classifiers = [
|
|
|
30
30
|
|
|
31
31
|
[project.urls]
|
|
32
32
|
Homepage = "https://eolas.fyi"
|
|
33
|
-
Documentation = "https://
|
|
33
|
+
Documentation = "https://docs.eolas.fyi/"
|
|
34
34
|
Repository = "https://github.com/phildonovan/eolas-data"
|
|
35
35
|
"Bug Tracker" = "https://github.com/phildonovan/eolas-data/issues"
|
|
36
36
|
|
|
37
37
|
[project.optional-dependencies]
|
|
38
38
|
dev = ["pytest", "responses", "pandas", "geopandas>=0.14", "shapely>=2.0", "typer>=0.12", "rich>=13"]
|
|
39
39
|
polars = ["polars>=0.20"]
|
|
40
|
-
plot = ["matplotlib>=3.5"]
|
|
41
40
|
geo = ["geopandas>=0.14", "shapely>=2.0"]
|
|
42
41
|
cli = ["typer>=0.12", "rich>=13"]
|
|
43
42
|
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import pandas as pd
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class Dataset(pd.DataFrame):
|
|
7
|
-
"""A pandas DataFrame with eolas dataset metadata.
|
|
8
|
-
|
|
9
|
-
Behaves exactly like a DataFrame — all pandas operations work normally.
|
|
10
|
-
Extra attributes:
|
|
11
|
-
eolas_name: Dataset identifier (e.g. ``"nz_cpi"``).
|
|
12
|
-
eolas_source: Data source label (e.g. ``"Stats NZ"``).
|
|
13
|
-
"""
|
|
14
|
-
|
|
15
|
-
_metadata = ["eolas_name", "eolas_source"]
|
|
16
|
-
|
|
17
|
-
@property
|
|
18
|
-
def _constructor(self):
|
|
19
|
-
return Dataset
|
|
20
|
-
|
|
21
|
-
def __repr__(self) -> str:
|
|
22
|
-
name = getattr(self, "eolas_name", "") or ""
|
|
23
|
-
source = getattr(self, "eolas_source", "") or ""
|
|
24
|
-
if name:
|
|
25
|
-
header = f"# Dataset: {name}"
|
|
26
|
-
if source:
|
|
27
|
-
header += f" [{source}]"
|
|
28
|
-
header += f"\n# {len(self)} rows\n"
|
|
29
|
-
return header + pd.DataFrame.__repr__(self)
|
|
30
|
-
return pd.DataFrame.__repr__(self)
|
|
31
|
-
|
|
32
|
-
def plot_dataset(self, ax=None, **kwargs):
|
|
33
|
-
"""Quick line chart using matplotlib.
|
|
34
|
-
|
|
35
|
-
Returns the matplotlib Axes object so you can customise further.
|
|
36
|
-
Requires matplotlib: ``pip install eolas-data[plot]``.
|
|
37
|
-
"""
|
|
38
|
-
try:
|
|
39
|
-
import matplotlib.pyplot as plt
|
|
40
|
-
except ImportError:
|
|
41
|
-
raise ImportError(
|
|
42
|
-
"matplotlib is required for plot_dataset(). "
|
|
43
|
-
"Install with: pip install eolas-data[plot]"
|
|
44
|
-
)
|
|
45
|
-
|
|
46
|
-
date_col = "date" if "date" in self.columns else self.columns[0]
|
|
47
|
-
value_col = "value" if "value" in self.columns else self.columns[1]
|
|
48
|
-
|
|
49
|
-
if ax is None:
|
|
50
|
-
_, ax = plt.subplots(figsize=(10, 4))
|
|
51
|
-
|
|
52
|
-
ax.plot(self[date_col], self[value_col], color="#2563eb", linewidth=1.5, **kwargs)
|
|
53
|
-
|
|
54
|
-
name = getattr(self, "eolas_name", "") or ""
|
|
55
|
-
source = getattr(self, "eolas_source", "") or ""
|
|
56
|
-
|
|
57
|
-
if name:
|
|
58
|
-
ax.set_title(name, fontweight="bold", fontsize=13)
|
|
59
|
-
ax.set_xlabel("")
|
|
60
|
-
ax.spines[["top", "right"]].set_visible(False)
|
|
61
|
-
|
|
62
|
-
caption = f"Source: {source} · eolas.fyi" if source else "eolas.fyi"
|
|
63
|
-
ax.figure.text(0.99, 0.01, caption, ha="right", fontsize=8, color="#9ca3af")
|
|
64
|
-
|
|
65
|
-
plt.tight_layout()
|
|
66
|
-
return ax
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|