ga-gataframe 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.
@@ -0,0 +1,14 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ ## 0.1.0 - 2026-09-02
6
+
7
+ - Prepared the package for the future `andreagemma/gataframe` GitHub repository.
8
+ - Moved the import package to `src/gataframe`.
9
+ - Added project metadata, CI/release workflows, documentation, tests, and MIT
10
+ license information for GataFrame.
11
+ - Fixed valid `GataFrame` column operations that were rejected by overly broad
12
+ assertion checks.
13
+ - Removed the serializer helper from the public package and documentation.
14
+
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Andrea Gemma
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,5 @@
1
+ include LICENSE
2
+ include CHANGELOG.md
3
+ include README.md
4
+ recursive-include docs *.md
5
+ recursive-include src/gataframe py.typed
@@ -0,0 +1,200 @@
1
+ Metadata-Version: 2.4
2
+ Name: ga-gataframe
3
+ Version: 0.1.0
4
+ Summary: DuckDB-backed dataframe helpers for tabular and geospatial data workflows.
5
+ Author: Andrea Gemma
6
+ License-Expression: MIT
7
+ Project-URL: Documentation, https://github.com/andreagemma/gataframe#readme
8
+ Project-URL: Issues, https://github.com/andreagemma/gataframe/issues
9
+ Project-URL: Source, https://github.com/andreagemma/gataframe
10
+ Keywords: gataframe,duckdb,dataframe,pandas,geopandas,etl
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3 :: Only
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
19
+ Classifier: Topic :: Database :: Front-Ends
20
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
+ Classifier: Typing :: Typed
22
+ Requires-Python: >=3.10
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: duckdb>=1.1
26
+ Requires-Dist: geopandas>=0.14
27
+ Requires-Dist: pandas>=2.0
28
+ Requires-Dist: pydantic>=2.0
29
+ Provides-Extra: test
30
+ Requires-Dist: pytest>=8.0; extra == "test"
31
+ Requires-Dist: pytest-cov>=5.0; extra == "test"
32
+ Provides-Extra: dev
33
+ Requires-Dist: build>=1.2; extra == "dev"
34
+ Requires-Dist: joblib>=1.4; extra == "dev"
35
+ Requires-Dist: mypy>=1.10; extra == "dev"
36
+ Requires-Dist: pytest>=8.0; extra == "dev"
37
+ Requires-Dist: pytest-cov>=5.0; extra == "dev"
38
+ Requires-Dist: ruff>=0.5; extra == "dev"
39
+ Requires-Dist: twine>=5.1; extra == "dev"
40
+ Provides-Extra: parallel
41
+ Requires-Dist: joblib>=1.4; extra == "parallel"
42
+ Dynamic: license-file
43
+
44
+ # GataFrame
45
+
46
+ [![CI](https://github.com/andreagemma/gataframe/actions/workflows/ci.yml/badge.svg)](https://github.com/andreagemma/gataframe/actions/workflows/ci.yml)
47
+ [![PyPI](https://img.shields.io/pypi/v/ga-gataframe.svg)](https://pypi.org/project/ga-gataframe/)
48
+ [![Python](https://img.shields.io/pypi/pyversions/ga-gataframe.svg)](https://pypi.org/project/ga-gataframe/)
49
+
50
+ GataFrame is a lightweight Python library built around DuckDB relations. It
51
+ adds a dataframe-style wrapper plus file and database read-write helpers for
52
+ tabular and geospatial workflows.
53
+
54
+ The PyPI distribution is named `ga-gataframe`; the import package is named
55
+ `gataframe`.
56
+
57
+ ## Installation
58
+
59
+ ```bash
60
+ python -m pip install ga-gataframe
61
+ ```
62
+
63
+ Development and test tools are available as extras:
64
+
65
+ ```bash
66
+ python -m pip install -e ".[test]"
67
+ python -m pip install -e ".[dev]"
68
+ ```
69
+
70
+ Optional parallel cleanup helpers are available with:
71
+
72
+ ```bash
73
+ python -m pip install -e ".[parallel]"
74
+ ```
75
+
76
+ ## Quick Start
77
+
78
+ ```python
79
+ import pandas as pd
80
+
81
+ from gataframe import connect
82
+
83
+ engine = connect(extensions=None)
84
+
85
+ gf = engine.read(pd.DataFrame({"id": [1, 2], "value": [10, 20]}))
86
+ result = gf.withColumn("double_value", "value * 2").filter("double_value > 20").toPandas()
87
+
88
+ assert result["double_value"].tolist() == [40]
89
+
90
+ engine.close()
91
+ ```
92
+
93
+ ## GataFrame
94
+
95
+ `GataFrame` wraps a `duckdb.DuckDBPyRelation` and keeps operations chainable.
96
+ Most methods return a new `GataFrame` unless `inplace=True` is passed.
97
+
98
+ ```python
99
+ import pandas as pd
100
+
101
+ from gataframe import connect
102
+
103
+ engine = connect(extensions=None)
104
+ gf = engine.read(pd.DataFrame({"a": [1, 2], "b": [3, 4]}))
105
+
106
+ out = (
107
+ gf.withColumn("total", "a + b")
108
+ .renameColumn("total", "sum_ab")
109
+ .replaceColumn("sum_ab", "sum_ab * 10")
110
+ .select("a", "sum_ab")
111
+ )
112
+
113
+ assert out.columns == ["a", "sum_ab"]
114
+ ```
115
+
116
+ Common methods include:
117
+
118
+ - `withColumn(name, expression)` and `replaceColumn(name, expression)`
119
+ - `renameColumn(old, new)` and `excludeColumn(*columns)`
120
+ - `select(*columns)`, `filter(expression)`, and `limit(n)`
121
+ - `createTable(...)`, `createView(...)`, `dropTable(...)`, and `dropView(...)`
122
+ - `toPandas()`, `toGeoPandas(...)`, and `toPandasOrGeoPandas(...)`
123
+
124
+ ## Engine
125
+
126
+ `Engine` owns the DuckDB connection and handles input/output.
127
+
128
+ ```python
129
+ from gataframe import connect
130
+
131
+ engine = connect(extensions=None, file_based=False)
132
+
133
+ gf = engine.read("data.csv", header=True)
134
+ engine.write(gf, "out.parquet", mode="overwrite")
135
+
136
+ engine.close()
137
+ ```
138
+
139
+ Supported readers and writers are inferred from file extensions where possible:
140
+ CSV, JSON, Parquet, GeoParquet, GeoJSON, GeoPackage, Shapefile, SQLite, and
141
+ PostgreSQL connection URLs.
142
+
143
+ DuckDB extensions are loaded only when requested by the caller or needed by a
144
+ specific geospatial/database operation.
145
+
146
+ ## API Summary
147
+
148
+ - `connect(logger=None, extensions=None, options=None, file_based=False, file=None)`
149
+ - `read(engine, source, format=None, pre_limit=None, limit=None, ...)`
150
+ - `write(engine, df, destination, mode="overwrite", partitionBy=None, ...)`
151
+ - `Engine.connect(...)`
152
+ - `Engine.read(source, format=None, ...)`
153
+ - `Engine.write(df, destination, mode="overwrite", ...)`
154
+ - `GataFrame.withColumn(...)`, `replaceColumn(...)`, `renameColumn(...)`
155
+ - `GataFrame.select(...)`, `filter(...)`, `limit(...)`, `union(...)`
156
+ - `GataFrame.toPandas()`, `toGeoPandas(...)`, and `toPandasOrGeoPandas(...)`
157
+
158
+ ## Development
159
+
160
+ GataFrame supports Python 3.10 and newer.
161
+
162
+ ```bash
163
+ python -m pip install -e ".[dev]"
164
+ python -m compileall -q src
165
+ python -m pytest --cov=gataframe --cov-report=term-missing
166
+ ruff format --check .
167
+ ruff check .
168
+ mypy
169
+ python -m pip check
170
+ python -m build
171
+ python -m twine check dist/*
172
+ ```
173
+
174
+ ## GitHub Repository Setup
175
+
176
+ This project is prepared for the future repository `andreagemma/gataframe`.
177
+
178
+ 1. Create the empty repository on GitHub.
179
+ 2. Initialize the local repository if needed and push the project to `main`.
180
+ 3. Confirm the CI workflow passes on GitHub.
181
+ 4. Configure the PyPI Trusted Publisher for project `ga-gataframe`, owner
182
+ `andreagemma`, repository `gataframe`, workflow `release.yml`, and
183
+ environment `pypi`.
184
+
185
+ ## Releases
186
+
187
+ `src/gataframe/_version.py` is the only version source. To publish a release:
188
+
189
+ 1. Update `__version__` in `_version.py` and commit the release changes.
190
+ 2. Push `main` and wait for CI to pass.
191
+ 3. Run the **Create release** GitHub Actions workflow. With no override it
192
+ creates the `v<version>` tag, creates release notes, and dispatches the build
193
+ and PyPI publication workflow.
194
+
195
+ PyPI versions are immutable. Increment `_version.py` before publishing different
196
+ content.
197
+
198
+ ## License
199
+
200
+ GataFrame is distributed under the MIT License. See [LICENSE](LICENSE).
@@ -0,0 +1,157 @@
1
+ # GataFrame
2
+
3
+ [![CI](https://github.com/andreagemma/gataframe/actions/workflows/ci.yml/badge.svg)](https://github.com/andreagemma/gataframe/actions/workflows/ci.yml)
4
+ [![PyPI](https://img.shields.io/pypi/v/ga-gataframe.svg)](https://pypi.org/project/ga-gataframe/)
5
+ [![Python](https://img.shields.io/pypi/pyversions/ga-gataframe.svg)](https://pypi.org/project/ga-gataframe/)
6
+
7
+ GataFrame is a lightweight Python library built around DuckDB relations. It
8
+ adds a dataframe-style wrapper plus file and database read-write helpers for
9
+ tabular and geospatial workflows.
10
+
11
+ The PyPI distribution is named `ga-gataframe`; the import package is named
12
+ `gataframe`.
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ python -m pip install ga-gataframe
18
+ ```
19
+
20
+ Development and test tools are available as extras:
21
+
22
+ ```bash
23
+ python -m pip install -e ".[test]"
24
+ python -m pip install -e ".[dev]"
25
+ ```
26
+
27
+ Optional parallel cleanup helpers are available with:
28
+
29
+ ```bash
30
+ python -m pip install -e ".[parallel]"
31
+ ```
32
+
33
+ ## Quick Start
34
+
35
+ ```python
36
+ import pandas as pd
37
+
38
+ from gataframe import connect
39
+
40
+ engine = connect(extensions=None)
41
+
42
+ gf = engine.read(pd.DataFrame({"id": [1, 2], "value": [10, 20]}))
43
+ result = gf.withColumn("double_value", "value * 2").filter("double_value > 20").toPandas()
44
+
45
+ assert result["double_value"].tolist() == [40]
46
+
47
+ engine.close()
48
+ ```
49
+
50
+ ## GataFrame
51
+
52
+ `GataFrame` wraps a `duckdb.DuckDBPyRelation` and keeps operations chainable.
53
+ Most methods return a new `GataFrame` unless `inplace=True` is passed.
54
+
55
+ ```python
56
+ import pandas as pd
57
+
58
+ from gataframe import connect
59
+
60
+ engine = connect(extensions=None)
61
+ gf = engine.read(pd.DataFrame({"a": [1, 2], "b": [3, 4]}))
62
+
63
+ out = (
64
+ gf.withColumn("total", "a + b")
65
+ .renameColumn("total", "sum_ab")
66
+ .replaceColumn("sum_ab", "sum_ab * 10")
67
+ .select("a", "sum_ab")
68
+ )
69
+
70
+ assert out.columns == ["a", "sum_ab"]
71
+ ```
72
+
73
+ Common methods include:
74
+
75
+ - `withColumn(name, expression)` and `replaceColumn(name, expression)`
76
+ - `renameColumn(old, new)` and `excludeColumn(*columns)`
77
+ - `select(*columns)`, `filter(expression)`, and `limit(n)`
78
+ - `createTable(...)`, `createView(...)`, `dropTable(...)`, and `dropView(...)`
79
+ - `toPandas()`, `toGeoPandas(...)`, and `toPandasOrGeoPandas(...)`
80
+
81
+ ## Engine
82
+
83
+ `Engine` owns the DuckDB connection and handles input/output.
84
+
85
+ ```python
86
+ from gataframe import connect
87
+
88
+ engine = connect(extensions=None, file_based=False)
89
+
90
+ gf = engine.read("data.csv", header=True)
91
+ engine.write(gf, "out.parquet", mode="overwrite")
92
+
93
+ engine.close()
94
+ ```
95
+
96
+ Supported readers and writers are inferred from file extensions where possible:
97
+ CSV, JSON, Parquet, GeoParquet, GeoJSON, GeoPackage, Shapefile, SQLite, and
98
+ PostgreSQL connection URLs.
99
+
100
+ DuckDB extensions are loaded only when requested by the caller or needed by a
101
+ specific geospatial/database operation.
102
+
103
+ ## API Summary
104
+
105
+ - `connect(logger=None, extensions=None, options=None, file_based=False, file=None)`
106
+ - `read(engine, source, format=None, pre_limit=None, limit=None, ...)`
107
+ - `write(engine, df, destination, mode="overwrite", partitionBy=None, ...)`
108
+ - `Engine.connect(...)`
109
+ - `Engine.read(source, format=None, ...)`
110
+ - `Engine.write(df, destination, mode="overwrite", ...)`
111
+ - `GataFrame.withColumn(...)`, `replaceColumn(...)`, `renameColumn(...)`
112
+ - `GataFrame.select(...)`, `filter(...)`, `limit(...)`, `union(...)`
113
+ - `GataFrame.toPandas()`, `toGeoPandas(...)`, and `toPandasOrGeoPandas(...)`
114
+
115
+ ## Development
116
+
117
+ GataFrame supports Python 3.10 and newer.
118
+
119
+ ```bash
120
+ python -m pip install -e ".[dev]"
121
+ python -m compileall -q src
122
+ python -m pytest --cov=gataframe --cov-report=term-missing
123
+ ruff format --check .
124
+ ruff check .
125
+ mypy
126
+ python -m pip check
127
+ python -m build
128
+ python -m twine check dist/*
129
+ ```
130
+
131
+ ## GitHub Repository Setup
132
+
133
+ This project is prepared for the future repository `andreagemma/gataframe`.
134
+
135
+ 1. Create the empty repository on GitHub.
136
+ 2. Initialize the local repository if needed and push the project to `main`.
137
+ 3. Confirm the CI workflow passes on GitHub.
138
+ 4. Configure the PyPI Trusted Publisher for project `ga-gataframe`, owner
139
+ `andreagemma`, repository `gataframe`, workflow `release.yml`, and
140
+ environment `pypi`.
141
+
142
+ ## Releases
143
+
144
+ `src/gataframe/_version.py` is the only version source. To publish a release:
145
+
146
+ 1. Update `__version__` in `_version.py` and commit the release changes.
147
+ 2. Push `main` and wait for CI to pass.
148
+ 3. Run the **Create release** GitHub Actions workflow. With no override it
149
+ creates the `v<version>` tag, creates release notes, and dispatches the build
150
+ and PyPI publication workflow.
151
+
152
+ PyPI versions are immutable. Increment `_version.py` before publishing different
153
+ content.
154
+
155
+ ## License
156
+
157
+ GataFrame is distributed under the MIT License. See [LICENSE](LICENSE).
@@ -0,0 +1,43 @@
1
+ # API Reference
2
+
3
+ ## `connect`
4
+
5
+ ```python
6
+ connect(logger=None, extensions=None, options=None, file_based=False, file=None)
7
+ ```
8
+
9
+ Creates an `Engine`. The package-level helper defaults to `extensions=None` so
10
+ basic dataframe work does not try to install DuckDB extensions.
11
+
12
+ ## `Engine`
13
+
14
+ ```python
15
+ Engine.connect(...)
16
+ engine.read(source, format=None, pre_limit=None, limit=None, ...)
17
+ engine.write(df, destination, mode="overwrite", ...)
18
+ ```
19
+
20
+ `Engine` owns the DuckDB connection. It reads Pandas dataframes, `GataFrame`
21
+ instances, and supported file/database sources into DuckDB relations, then wraps
22
+ them as `GataFrame`.
23
+
24
+ Supported file formats include CSV, JSON, Parquet, GeoParquet, GeoJSON,
25
+ GeoPackage, Shapefile, SQLite, and PostgreSQL URLs.
26
+
27
+ ## `GataFrame`
28
+
29
+ ```python
30
+ GataFrame(relation, con=None, alias=None, description=None, version=0)
31
+ ```
32
+
33
+ Wraps a `duckdb.DuckDBPyRelation` and returns chainable `GataFrame` instances.
34
+
35
+ Main methods:
36
+
37
+ - `withColumn(name, expression)` and `replaceColumn(name, expression)`
38
+ - `renameColumn(old, new)` and `excludeColumn(*columns)`
39
+ - `select(*columns)`, `filter(expression)`, and `limit(n)`
40
+ - `createTable(...)`, `createView(...)`, `dropTable(...)`, and `dropView(...)`
41
+ - `union(other)`, `sql(sql)`, and `execute(sql)`
42
+ - `as_type(columns)`
43
+ - `toPandas()`, `toGeoPandas(...)`, and `toPandasOrGeoPandas(...)`
@@ -0,0 +1,8 @@
1
+ # GataFrame Documentation
2
+
3
+ GataFrame wraps DuckDB relations with dataframe-style helpers for tabular,
4
+ geospatial, file, and database workflows.
5
+
6
+ - See [API Reference](api.md) for the public classes and methods.
7
+ - See the project [README](../README.md) for installation, quick start,
8
+ development, release, and GitHub setup instructions.
@@ -0,0 +1,111 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "ga-gataframe"
7
+ dynamic = ["version"]
8
+ description = "DuckDB-backed dataframe helpers for tabular and geospatial data workflows."
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = "MIT"
12
+ license-files = ["LICENSE"]
13
+ authors = [
14
+ { name = "Andrea Gemma" }
15
+ ]
16
+ keywords = ["gataframe", "duckdb", "dataframe", "pandas", "geopandas", "etl"]
17
+ classifiers = [
18
+ "Development Status :: 3 - Alpha",
19
+ "Intended Audience :: Developers",
20
+ "Programming Language :: Python :: 3 :: Only",
21
+ "Programming Language :: Python :: 3.10",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Programming Language :: Python :: 3.12",
24
+ "Programming Language :: Python :: 3.13",
25
+ "Programming Language :: Python :: 3.14",
26
+ "Topic :: Database :: Front-Ends",
27
+ "Topic :: Software Development :: Libraries :: Python Modules",
28
+ "Typing :: Typed"
29
+ ]
30
+ dependencies = [
31
+ "duckdb>=1.1",
32
+ "geopandas>=0.14",
33
+ "pandas>=2.0",
34
+ "pydantic>=2.0"
35
+ ]
36
+
37
+ [project.optional-dependencies]
38
+ test = [
39
+ "pytest>=8.0",
40
+ "pytest-cov>=5.0"
41
+ ]
42
+ dev = [
43
+ "build>=1.2",
44
+ "joblib>=1.4",
45
+ "mypy>=1.10",
46
+ "pytest>=8.0",
47
+ "pytest-cov>=5.0",
48
+ "ruff>=0.5",
49
+ "twine>=5.1"
50
+ ]
51
+ parallel = [
52
+ "joblib>=1.4"
53
+ ]
54
+
55
+ [project.urls]
56
+ Documentation = "https://github.com/andreagemma/gataframe#readme"
57
+ Issues = "https://github.com/andreagemma/gataframe/issues"
58
+ Source = "https://github.com/andreagemma/gataframe"
59
+
60
+ [tool.setuptools]
61
+ package-dir = {"" = "src"}
62
+
63
+ [tool.setuptools.packages.find]
64
+ where = ["src"]
65
+
66
+ [tool.setuptools.package-data]
67
+ gataframe = ["py.typed"]
68
+
69
+ [tool.setuptools.dynamic]
70
+ version = {attr = "gataframe._version.__version__"}
71
+
72
+ [tool.pytest.ini_options]
73
+ testpaths = ["tests"]
74
+ addopts = "-ra --strict-markers"
75
+
76
+ [tool.coverage.run]
77
+ branch = true
78
+ source = ["gataframe"]
79
+
80
+ [tool.ruff]
81
+ line-length = 120
82
+ target-version = "py310"
83
+ exclude = [
84
+ ".venv",
85
+ "build",
86
+ "dist",
87
+ "src/gataframe.egg-info",
88
+ "venv",
89
+ "wheel-smoke-test"
90
+ ]
91
+
92
+ [tool.ruff.lint]
93
+ select = ["E9", "F63", "F7", "F82"]
94
+
95
+ [tool.mypy]
96
+ python_version = "3.10"
97
+ files = ["src/gataframe"]
98
+ warn_unused_configs = true
99
+ check_untyped_defs = true
100
+ follow_imports = "skip"
101
+ no_site_packages = true
102
+ ignore_missing_imports = true
103
+ disable_error_code = ["import-untyped"]
104
+
105
+ [[tool.mypy.overrides]]
106
+ module = [
107
+ "gataframe.engine",
108
+ "gataframe.files",
109
+ "gataframe.gata_frame"
110
+ ]
111
+ ignore_errors = true
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+