dataflux-core 0.1.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.
Files changed (102) hide show
  1. dataflux_core-0.1.0/.github/workflows/docs.yml +28 -0
  2. dataflux_core-0.1.0/.gitignore +122 -0
  3. dataflux_core-0.1.0/.python-version +1 -0
  4. dataflux_core-0.1.0/LICENSE +21 -0
  5. dataflux_core-0.1.0/PKG-INFO +400 -0
  6. dataflux_core-0.1.0/README.md +362 -0
  7. dataflux_core-0.1.0/docs/advanced/architecture.md +74 -0
  8. dataflux_core-0.1.0/docs/advanced/contributing.md +82 -0
  9. dataflux_core-0.1.0/docs/advanced/writing-a-provider.md +177 -0
  10. dataflux_core-0.1.0/docs/api-reference/base-provider.md +112 -0
  11. dataflux_core-0.1.0/docs/api-reference/exceptions.md +245 -0
  12. dataflux_core-0.1.0/docs/api-reference/flux.md +166 -0
  13. dataflux_core-0.1.0/docs/api-reference/models.md +93 -0
  14. dataflux_core-0.1.0/docs/changelog.md +29 -0
  15. dataflux_core-0.1.0/docs/getting-started/core-concepts.md +141 -0
  16. dataflux_core-0.1.0/docs/getting-started/installation.md +52 -0
  17. dataflux_core-0.1.0/docs/getting-started/quickstart.md +95 -0
  18. dataflux_core-0.1.0/docs/guide/caching.md +94 -0
  19. dataflux_core-0.1.0/docs/guide/error-handling.md +128 -0
  20. dataflux_core-0.1.0/docs/guide/exporting-data.md +107 -0
  21. dataflux_core-0.1.0/docs/guide/inspecting-datasets.md +62 -0
  22. dataflux_core-0.1.0/docs/guide/pulling-datasets.md +75 -0
  23. dataflux_core-0.1.0/docs/guide/searching.md +143 -0
  24. dataflux_core-0.1.0/docs/index.md +128 -0
  25. dataflux_core-0.1.0/docs/providers/huggingface.md +62 -0
  26. dataflux_core-0.1.0/docs/providers/kaggle.md +107 -0
  27. dataflux_core-0.1.0/docs/providers/overview.md +72 -0
  28. dataflux_core-0.1.0/docs/providers/seaborn.md +56 -0
  29. dataflux_core-0.1.0/docs/providers/sklearn.md +56 -0
  30. dataflux_core-0.1.0/docs/providers/statsmodels.md +59 -0
  31. dataflux_core-0.1.0/docs/providers/torchvision.md +71 -0
  32. dataflux_core-0.1.0/docs/providers/uci.md +67 -0
  33. dataflux_core-0.1.0/docs/providers/vega.md +57 -0
  34. dataflux_core-0.1.0/docs/providers/worldbank.md +74 -0
  35. dataflux_core-0.1.0/mkdocs.yml +74 -0
  36. dataflux_core-0.1.0/pyproject.toml +69 -0
  37. dataflux_core-0.1.0/src/dataflux/__init__.py +4 -0
  38. dataflux_core-0.1.0/src/dataflux/__version__.py +1 -0
  39. dataflux_core-0.1.0/src/dataflux/cache.py +122 -0
  40. dataflux_core-0.1.0/src/dataflux/config.py +18 -0
  41. dataflux_core-0.1.0/src/dataflux/display/__init__.py +0 -0
  42. dataflux_core-0.1.0/src/dataflux/display/console.py +4 -0
  43. dataflux_core-0.1.0/src/dataflux/display/info.py +150 -0
  44. dataflux_core-0.1.0/src/dataflux/display/search.py +122 -0
  45. dataflux_core-0.1.0/src/dataflux/display/theme.py +32 -0
  46. dataflux_core-0.1.0/src/dataflux/display/utils.py +138 -0
  47. dataflux_core-0.1.0/src/dataflux/exceptions.py +150 -0
  48. dataflux_core-0.1.0/src/dataflux/export.py +62 -0
  49. dataflux_core-0.1.0/src/dataflux/flux.py +55 -0
  50. dataflux_core-0.1.0/src/dataflux/models/__init__.py +0 -0
  51. dataflux_core-0.1.0/src/dataflux/models/dataset.py +15 -0
  52. dataflux_core-0.1.0/src/dataflux/models/search_result.py +10 -0
  53. dataflux_core-0.1.0/src/dataflux/providers/__init__.py +0 -0
  54. dataflux_core-0.1.0/src/dataflux/providers/base.py +23 -0
  55. dataflux_core-0.1.0/src/dataflux/providers/huggingface.py +91 -0
  56. dataflux_core-0.1.0/src/dataflux/providers/kaggle.py +85 -0
  57. dataflux_core-0.1.0/src/dataflux/providers/seaborn.py +66 -0
  58. dataflux_core-0.1.0/src/dataflux/providers/sklearn.py +67 -0
  59. dataflux_core-0.1.0/src/dataflux/providers/statsmodels.py +66 -0
  60. dataflux_core-0.1.0/src/dataflux/providers/torchvision.py +80 -0
  61. dataflux_core-0.1.0/src/dataflux/providers/uci.py +78 -0
  62. dataflux_core-0.1.0/src/dataflux/providers/vega_datasets.py +64 -0
  63. dataflux_core-0.1.0/src/dataflux/providers/worldbank.py +73 -0
  64. dataflux_core-0.1.0/src/dataflux/registry.py +38 -0
  65. dataflux_core-0.1.0/src/dataflux/resolver.py +30 -0
  66. dataflux_core-0.1.0/src/dataflux/resources/kaggle_index.json +365901 -0
  67. dataflux_core-0.1.0/src/dataflux/resources/seaborn_dataset.py +24 -0
  68. dataflux_core-0.1.0/src/dataflux/resources/sklearn_dataset.py +17 -0
  69. dataflux_core-0.1.0/src/dataflux/resources/statsmodels_dataset.py +30 -0
  70. dataflux_core-0.1.0/src/dataflux/resources/torch_vision_dataset.py +89 -0
  71. dataflux_core-0.1.0/src/dataflux/tests/conftest.py +33 -0
  72. dataflux_core-0.1.0/src/dataflux/tests/display/test_info.py +159 -0
  73. dataflux_core-0.1.0/src/dataflux/tests/display/test_search.py +83 -0
  74. dataflux_core-0.1.0/src/dataflux/tests/models/test_dataset_info.py +46 -0
  75. dataflux_core-0.1.0/src/dataflux/tests/models/test_search_result.py +28 -0
  76. dataflux_core-0.1.0/src/dataflux/tests/providers/test_hugging.py +93 -0
  77. dataflux_core-0.1.0/src/dataflux/tests/providers/test_kaggle.py +94 -0
  78. dataflux_core-0.1.0/src/dataflux/tests/providers/test_seaborn.py +88 -0
  79. dataflux_core-0.1.0/src/dataflux/tests/providers/test_sklearn.py +92 -0
  80. dataflux_core-0.1.0/src/dataflux/tests/providers/test_statsmodels.py +89 -0
  81. dataflux_core-0.1.0/src/dataflux/tests/providers/test_torchvision.py +90 -0
  82. dataflux_core-0.1.0/src/dataflux/tests/providers/test_uci.py +92 -0
  83. dataflux_core-0.1.0/src/dataflux/tests/providers/test_vega.py +90 -0
  84. dataflux_core-0.1.0/src/dataflux/tests/providers/test_worldbank.py +111 -0
  85. dataflux_core-0.1.0/src/dataflux/tests/resources/test_resources.py +80 -0
  86. dataflux_core-0.1.0/src/dataflux/tests/test_exceptions.py +20 -0
  87. dataflux_core-0.1.0/src/dataflux/tests/test_export.py +146 -0
  88. dataflux_core-0.1.0/src/dataflux/tests/test_flux.py +40 -0
  89. dataflux_core-0.1.0/src/dataflux/tests/test_models.py +30 -0
  90. dataflux_core-0.1.0/src/dataflux/tests/test_registry.py +149 -0
  91. dataflux_core-0.1.0/src/dataflux/tests/test_resolver.py +77 -0
  92. dataflux_core-0.1.0/src/dataflux/tests/utils/test_cache.py +173 -0
  93. dataflux_core-0.1.0/src/dataflux/tests/utils/test_download.py +135 -0
  94. dataflux_core-0.1.0/src/dataflux/tests/utils/test_filesystem.py +128 -0
  95. dataflux_core-0.1.0/src/dataflux/tests/utils/test_fingerprint.py +114 -0
  96. dataflux_core-0.1.0/src/dataflux/tests/utils/test_search_utils.py +152 -0
  97. dataflux_core-0.1.0/src/dataflux/utils/__init__.py +0 -0
  98. dataflux_core-0.1.0/src/dataflux/utils/download.py +110 -0
  99. dataflux_core-0.1.0/src/dataflux/utils/filesystem.py +89 -0
  100. dataflux_core-0.1.0/src/dataflux/utils/fingerprint.py +155 -0
  101. dataflux_core-0.1.0/src/dataflux/utils/search.py +66 -0
  102. dataflux_core-0.1.0/uv.lock +2146 -0
@@ -0,0 +1,28 @@
1
+ name: Deploy Docs
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ paths:
8
+ - "docs/**"
9
+ - "mkdocs.yml"
10
+
11
+ permissions:
12
+ contents: write
13
+
14
+ jobs:
15
+ deploy:
16
+ runs-on: ubuntu-latest
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+
20
+ - uses: actions/setup-python@v5
21
+ with:
22
+ python-version: "3.x"
23
+
24
+ - name: Install mkdocs-material
25
+ run: pip install mkdocs-material
26
+
27
+ - name: Deploy
28
+ run: mkdocs gh-deploy --force
@@ -0,0 +1,122 @@
1
+ # ============================================================================
2
+ # Python
3
+ # ============================================================================
4
+
5
+ __pycache__/
6
+ *.py[cod]
7
+ *$py.class
8
+
9
+ # C Extensions
10
+ *.so
11
+ *.pyd
12
+ *.dll
13
+
14
+ # ============================================================================
15
+ # Virtual Environments
16
+ # ============================================================================
17
+
18
+ .venv/
19
+ venv/
20
+ env/
21
+ ENV/
22
+
23
+ # ============================================================================
24
+ # Packaging
25
+ # ============================================================================
26
+
27
+ build/
28
+ dist/
29
+ wheels/
30
+ *.egg-info/
31
+ .eggs/
32
+
33
+ pip-wheel-metadata/
34
+
35
+ # ============================================================================
36
+ # Test & Coverage
37
+ # ============================================================================
38
+
39
+ .pytest_cache/
40
+ .coverage
41
+ .coverage.*
42
+ htmlcov/
43
+
44
+ # ============================================================================
45
+ # Type Checkers / Linters
46
+ # ============================================================================
47
+
48
+ .mypy_cache/
49
+ .pyright/
50
+ .ruff_cache/
51
+ .dmypy.json
52
+
53
+ # ============================================================================
54
+ # Jupyter
55
+ # ============================================================================
56
+
57
+ .ipynb_checkpoints/
58
+
59
+ # ============================================================================
60
+ # IDEs
61
+ # ============================================================================
62
+
63
+ .vscode/
64
+ .idea/
65
+
66
+ # ============================================================================
67
+ # Operating System
68
+ # ============================================================================
69
+
70
+ .DS_Store
71
+ Thumbs.db
72
+ desktop.ini
73
+
74
+ # ============================================================================
75
+ # Logs
76
+ # ============================================================================
77
+
78
+ *.log
79
+
80
+ # ============================================================================
81
+ # Environment Variables
82
+ # ============================================================================
83
+
84
+ .env
85
+ .env.*
86
+
87
+ # ============================================================================
88
+ # Temporary Files
89
+ # ============================================================================
90
+
91
+ tmp/
92
+ temp/
93
+ *.tmp
94
+
95
+ # ============================================================================
96
+ # DataFlux Cache
97
+ # ============================================================================
98
+
99
+ .cache/
100
+ downloads/
101
+ datasets/
102
+
103
+ # ============================================================================
104
+ # Python Build Artifacts
105
+ # ============================================================================
106
+
107
+ *.manifest
108
+ *.spec
109
+
110
+ # ============================================================================
111
+ # Documentation
112
+ # ============================================================================
113
+
114
+ site/
115
+
116
+ # ============================================================================
117
+ # Misc
118
+ # ============================================================================
119
+
120
+ *.bak
121
+ *.swp
122
+ *.swo
@@ -0,0 +1 @@
1
+ 3.14
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Zeo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,400 @@
1
+ Metadata-Version: 2.4
2
+ Name: dataflux-core
3
+ Version: 0.1.0
4
+ Summary: A unified Python library for discovering, exploring, and loading datasets from multiple data providers.
5
+ Project-URL: Homepage, https://github.com/JustZeo/DataFlux
6
+ Project-URL: Repository, https://github.com/JustZeo/DataFlux
7
+ Project-URL: Documentation, https://justzeo.github.io/DataFlux/
8
+ Project-URL: Issues, https://github.com/JustZeo/DataFlux/issues
9
+ Project-URL: Changelog, https://justzeo.github.io/DataFlux/changelog/
10
+ Author-email: JustZeo <justzeo18@gmail.com>
11
+ License-Expression: MIT
12
+ License-File: LICENSE
13
+ Keywords: data,datasets,huggingface,kaggle,machine-learning,polars,uci
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Intended Audience :: Science/Research
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.14
20
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Requires-Python: >=3.14
23
+ Requires-Dist: datasets>=5.0.0
24
+ Requires-Dist: huggingface-hub>=1.24.0
25
+ Requires-Dist: kaggle>=2.2.4
26
+ Requires-Dist: kagglehub>=1.0.2
27
+ Requires-Dist: polars>=1.43.0
28
+ Requires-Dist: pyarrow>=25.0.0
29
+ Requires-Dist: rich>=15.0.0
30
+ Requires-Dist: scikit-learn>=1.9.0
31
+ Requires-Dist: seaborn>=0.13.2
32
+ Requires-Dist: statsmodels>=0.14.6
33
+ Requires-Dist: torchvision>=0.28.0
34
+ Requires-Dist: ucimlrepo>=0.0.7
35
+ Requires-Dist: vega-datasets>=0.9.0
36
+ Requires-Dist: wbgapi>=1.0.14
37
+ Description-Content-Type: text/markdown
38
+
39
+ # DataFlux
40
+
41
+ **One API. Every dataset.**
42
+
43
+ DataFlux is a universal dataset library for Python. Instead of learning a different package, auth flow, and return type for every dataset source, you interact with one consistent interface — `search()`, `info()`, `pull()` — and DataFlux handles the rest.
44
+
45
+ ```python
46
+ from dataflux import flux
47
+
48
+ results = flux.search("iris")
49
+ info = flux.info(results[0])
50
+ df = flux.pull(results[0])
51
+ ```
52
+
53
+ Whether the dataset lives on scikit-learn, UCI, Kaggle, Hugging Face, TorchVision, Seaborn, Statsmodels, Vega, or the World Bank — you never have to care. You get back the same shapes every time: a list of `SearchResult`, a `DatasetInfo`, and a `polars.DataFrame`.
54
+
55
+ ---
56
+
57
+ ## Why DataFlux
58
+
59
+ Every dataset provider does things differently:
60
+
61
+ ```python
62
+ # scikit-learn
63
+ from sklearn.datasets import load_iris
64
+ iris = load_iris(as_frame=True)
65
+
66
+ # UCI
67
+ from ucimlrepo import fetch_ucirepo
68
+ iris = fetch_ucirepo(id=53)
69
+
70
+ # Hugging Face
71
+ from datasets import load_dataset
72
+ dataset = load_dataset(...)
73
+
74
+ # Kaggle
75
+ # requires auth, zip downloads, manual extraction...
76
+ ```
77
+
78
+ Different function names, different auth requirements, different metadata formats, different return types. DataFlux hides all of that behind one contract:
79
+
80
+ ```python
81
+ results = flux.search("housing")
82
+ info = flux.info(results[0])
83
+ df = flux.pull(results[0])
84
+ ```
85
+
86
+ ---
87
+
88
+ ## Installation
89
+
90
+ ```bash
91
+ pip install dataflux
92
+ ```
93
+
94
+ or, if you're using [uv](https://github.com/astral-sh/uv):
95
+
96
+ ```bash
97
+ uv add dataflux
98
+ ```
99
+
100
+ ---
101
+
102
+ ## Quick Start
103
+
104
+ ```python
105
+ from dataflux import flux
106
+
107
+ # Search across every registered provider at once
108
+ flux.search("housing")
109
+
110
+ # Get results without the pretty console output
111
+ results = flux.search("housing", display=False)
112
+
113
+ # Inspect a dataset before committing to a download
114
+ flux.info(results[0])
115
+
116
+ # Pull the dataset as a Polars DataFrame
117
+ df = flux.pull(results[0])
118
+
119
+ # Export it to disk in whatever format you need
120
+ flux.export(df, "housing.csv")
121
+ ```
122
+
123
+ ---
124
+
125
+ ## Core Concepts
126
+
127
+ ### `search(query, *, raw=False, display=True, limit=10)`
128
+
129
+ Searches every registered provider for the query, merges and ranks the results, and returns a `list[SearchResult]`.
130
+
131
+ - **`display`** — when `True` (default), prints a formatted, colorized table via `rich`. Set to `False` to search silently (e.g. inside a script or pipeline).
132
+ - **`raw`** — when `True`, skips the pretty output entirely regardless of `display`.
133
+ - **`limit`** — caps how many results are shown in the pretty table (default `10`). The full, unranked result set is still returned; only the *displayed* table is capped.
134
+
135
+ Results are ranked across providers so that curated, canonical sources (like scikit-learn and UCI) surface above noisier, crowd-sourced sources (like Kaggle) for the same query.
136
+
137
+ If nothing matches, `search()` raises `DatasetNotFoundError` rather than silently returning an empty list.
138
+
139
+ ```python
140
+ results = flux.search("iris")
141
+ ```
142
+
143
+ ```
144
+ Search Results (10 of 303)
145
+ ┏━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┓
146
+ ┃ # ┃ Name ┃ Provider ┃ ID ┃ Description ┃
147
+ ┡━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━┩
148
+ │ 1 │ Iris │ uci │ 53 │ - │
149
+ │ 2 │ Iris │ sklearn │ iris │ - │
150
+ │ 3 │ Iris Species │ kaggle │ uciml/iris │ Classify iris │
151
+ │ │ │ │ │ plants into │
152
+ │ │ │ │ │ three species │
153
+ └────┴────────────────┴──────────┴────────────────┴────────────────┘
154
+
155
+ Showing the first 10 of 303 results.
156
+ Use raw=True to work with all returned results programmatically.
157
+ ```
158
+
159
+ ### `info(result, *, raw=False, display=True)`
160
+
161
+ Takes a `SearchResult` and returns a `DatasetInfo` describing it — row/feature counts, tasks, target columns, missing-value status, license/URL, and any provider-specific extras.
162
+
163
+ ```python
164
+ info = flux.info(results[0])
165
+ ```
166
+
167
+ ### `pull(result)`
168
+
169
+ Takes a `SearchResult` and returns a `polars.DataFrame` with the actual dataset loaded into memory. Every provider — regardless of its native format (pandas, CSV, JSON, image folders, etc.) — is normalized into the same Polars shape.
170
+
171
+ ```python
172
+ df = flux.pull(results[0])
173
+ ```
174
+
175
+ ### `export(df, path, *, overwrite=False, mkdir=True)`
176
+
177
+ Writes a Polars DataFrame to disk. The format is inferred from the file extension.
178
+
179
+ ```python
180
+ flux.export(df, "housing.csv")
181
+ flux.export(df, "housing.parquet")
182
+ flux.export(df, "nested/housing.json", overwrite=True)
183
+ ```
184
+
185
+ Supported extensions: `.csv`, `.parquet`, `.json`, `.ndjson`, `.ipc`, `.feather`, `.arrow`.
186
+
187
+ ---
188
+
189
+ ## Data Models
190
+
191
+ Every provider returns the exact same two data shapes, so downstream code never has to branch on provider.
192
+
193
+ ### `SearchResult`
194
+
195
+ ```python
196
+ @dataclass(slots=True)
197
+ class SearchResult:
198
+ id: str
199
+ name: str
200
+ provider: str
201
+ description: str | None = None
202
+ relevance: int = 0
203
+ ```
204
+
205
+ ### `DatasetInfo`
206
+
207
+ ```python
208
+ @dataclass(slots=True)
209
+ class DatasetInfo:
210
+ id: str | int
211
+ name: str
212
+ description: str | None
213
+ instances: int | None
214
+ features: int | None
215
+ tasks: list[str]
216
+ target: list[str]
217
+ has_missing_values: bool | None
218
+ provider: str
219
+ url: str | None
220
+ extra: dict[str, Any]
221
+ ```
222
+
223
+ ---
224
+
225
+ ## Supported Providers
226
+
227
+ | Provider | Category | Notes |
228
+ |---|---|---|
229
+ | **UCI** | Classical ML benchmarks | Live search against the UCI ML Repository API |
230
+ | **scikit-learn** | Toy datasets & tabular baselines | Bundled, always available offline |
231
+ | **Kaggle** | Community & competition datasets | Uses a periodically refreshed **offline index** — no login required (see below) |
232
+ | **Hugging Face** | NLP & web-scale datasets | Live search via the HF Hub |
233
+ | **TorchVision** | Computer vision datasets | Hand-maintained registry of well-known vision datasets |
234
+ | **Seaborn** | Statistical & visualization datasets | Small, fixed catalog |
235
+ | **Statsmodels** | Econometrics & time series | Small, fixed catalog |
236
+ | **Vega** | Data visualization benchmarks | Small, fixed catalog |
237
+ | **World Bank** | Global economic & social indicators | Country/time-series indicator data |
238
+
239
+ ### A note on Kaggle
240
+
241
+ Kaggle's dataset **search** API requires authentication even for public datasets — but DataFlux's core promise is that no provider should force you to log in just to discover what's available. To honor that, `KaggleProvider` ships with a **bundled, periodically refreshed offline index** instead of hitting Kaggle's live search endpoint. `pull()` still downloads the actual dataset live and auth-free, since Kaggle's public download endpoint doesn't gate on login.
242
+
243
+ The tradeoff: Kaggle search results are only as fresh as the last index refresh (updated on a recurring schedule via CI), not real-time. Every other provider's search is fully live.
244
+
245
+ If you specifically need live, up-to-the-minute Kaggle search, that's a deliberate scope decision left open for a future opt-in mode — not something DataFlux does by default.
246
+
247
+ ---
248
+
249
+ ## Provider Architecture
250
+
251
+ Every provider is independent and implements the same three-method contract:
252
+
253
+ ```python
254
+ class BaseProvider(ABC):
255
+
256
+ @property
257
+ @abstractmethod
258
+ def name(self) -> str:
259
+ """Unique provider name."""
260
+
261
+ @abstractmethod
262
+ def search(self, query: str) -> list[SearchResult]:
263
+ """Search datasets."""
264
+
265
+ @abstractmethod
266
+ def info(self, dataset: str) -> DatasetInfo:
267
+ """Return dataset metadata."""
268
+
269
+ @abstractmethod
270
+ def pull(self, dataset: str) -> pl.DataFrame:
271
+ """Download the requested dataset and return it as a DataFrame."""
272
+ ```
273
+
274
+ Providers are registered once, at startup, via a `ProviderRegistry`:
275
+
276
+ ```python
277
+ self._registry.register(UCIProvider())
278
+ self._registry.register(SKLearnProvider())
279
+ self._registry.register(KaggleProvider())
280
+ self._registry.register(HuggingFaceProvider())
281
+ self._registry.register(TorchVisionProvider())
282
+ self._registry.register(SeabornProvider())
283
+ self._registry.register(StatsModelsProvider())
284
+ self._registry.register(VegaDatasetsProvider())
285
+ self._registry.register(WorldBankProvider())
286
+ ```
287
+
288
+ A `Resolver` sits on top of the registry and handles two jobs:
289
+
290
+ - **`resolve_dataset(query)`** — fans a query out to every registered provider, merges the results, and ranks them (curated sources like UCI/scikit-learn are weighted above crowd-sourced sources like Kaggle for the same query).
291
+ - **`resolve_provider(name)`** — looks up a specific provider by name (used internally by `info()`/`pull()` to route a `SearchResult` back to the provider that produced it).
292
+
293
+ Adding a new provider means writing one class that implements `search()`/`info()`/`pull()` and registering it — nothing else in the library needs to change.
294
+
295
+ ---
296
+
297
+ ## Why Polars
298
+
299
+ DataFlux is Polars-first. Every dataset, regardless of source format, is normalized into a `polars.DataFrame`:
300
+
301
+ - Faster loading, lower memory usage than pandas for most workloads
302
+ - One consistent dataframe API across every provider
303
+ - Seamless handoff into other Polars-based tooling (e.g. [QualityClean](https://pypi.org/project/qualityclean/))
304
+
305
+ ```python
306
+ import dataflux as flux
307
+ import qualityclean as qc
308
+
309
+ df = flux.pull(flux.search("housing")[0])
310
+ clean_df = qc.clean(df)
311
+ ```
312
+
313
+ ---
314
+
315
+ ## Error Handling
316
+
317
+ DataFlux raises specific, catchable exceptions rather than leaking raw provider errors:
318
+
319
+ ```python
320
+ from dataflux.exceptions import (
321
+ DataFluxError, # base exception for everything below
322
+ ProviderNotFoundError,
323
+ DatasetNotFoundError,
324
+ InvalidDatasetError,
325
+ DatasetLoadError,
326
+ SearchError,
327
+ EmptySearchQueryError,
328
+ PullError,
329
+ DownloadError,
330
+ CacheError,
331
+ FileSystemError,
332
+ ExportError,
333
+ UnsupportedExportFormatError,
334
+ ExportFileExistsError,
335
+ InvalidExportDataError,
336
+ )
337
+ ```
338
+
339
+ ```python
340
+ from dataflux import flux
341
+ from dataflux.exceptions import DatasetNotFoundError
342
+
343
+ try:
344
+ flux.search("something that doesn't exist anywhere")
345
+ except DatasetNotFoundError:
346
+ print("No matches across any provider.")
347
+ ```
348
+
349
+ ---
350
+
351
+ ## Caching
352
+
353
+ DataFlux caches provider downloads locally under `~/.dataflux/`, namespaced per provider:
354
+
355
+ ```
356
+ ~/.dataflux/
357
+ ├── uci/
358
+ ├── kaggle/
359
+ ├── huggingface/
360
+ ├── torchvision/
361
+ └── tensorflow/
362
+ ```
363
+
364
+ Repeated `pull()` calls for the same dataset avoid re-downloading where the provider supports it.
365
+
366
+ ---
367
+
368
+ ## Project Status
369
+
370
+ DataFlux is at **v0.1.0** — all nine planned providers for this release are implemented and passing their own test suite (`tests/providers/`), alongside tests for the registry, resolver, models, display layer, and shared utilities (filesystem, caching, hashing/fingerprinting, download).
371
+
372
+ ### Roadmap
373
+
374
+ - [x] Provider contract (`BaseProvider`, `SearchResult`, `DatasetInfo`)
375
+ - [x] UCI, scikit-learn, Kaggle, Hugging Face, TorchVision, Seaborn, Statsmodels, Vega, World Bank providers
376
+ - [x] Ranked, multi-provider search
377
+ - [x] `export()` to CSV/Parquet/JSON/NDJSON/IPC/Feather/Arrow
378
+ - [x] Pretty (`rich`-based) console output for `search()`/`info()`
379
+ - [ ] Additional providers (TensorFlow Datasets, Zenodo, government open-data portals, local/custom datasets)
380
+ - [ ] Optional authenticated live-search mode for Kaggle
381
+ - [ ] Expanded documentation site
382
+
383
+ ### Design Principles
384
+
385
+ - One API for every dataset source — no provider-specific code required from the user.
386
+ - No provider should require authentication to search or discover data by default.
387
+ - Provider-agnostic architecture — adding a new source never touches existing ones.
388
+ - Polars-first for consistent, high-performance data handling.
389
+ - Standardized metadata (`SearchResult`, `DatasetInfo`) across every provider.
390
+ - Fail loudly and specifically (typed exceptions) rather than leaking raw provider errors.
391
+
392
+ ---
393
+
394
+ ## License
395
+
396
+ *(add your chosen license here — MIT, Apache-2.0, etc.)*
397
+
398
+ ## Contributing
399
+
400
+ *(add contribution guidelines here once ready to accept external PRs)*