fugue 0.9.7.dev2__tar.gz → 0.9.8__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.
- {fugue-0.9.7.dev2 → fugue-0.9.8}/PKG-INFO +4 -5
- {fugue-0.9.7.dev2 → fugue-0.9.8}/README.md +1 -1
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue.egg-info/PKG-INFO +4 -5
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_ray/_utils/io.py +37 -29
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_spark/_utils/misc.py +8 -10
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_spark/execution_engine.py +11 -4
- {fugue-0.9.7.dev2 → fugue-0.9.8}/pyproject.toml +5 -4
- {fugue-0.9.7.dev2 → fugue-0.9.8}/LICENSE +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/__init__.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/_utils/__init__.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/_utils/display.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/_utils/exception.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/_utils/interfaceless.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/_utils/io.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/_utils/misc.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/_utils/registry.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/api.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/bag/__init__.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/bag/array_bag.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/bag/bag.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/collections/__init__.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/collections/partition.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/collections/sql.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/collections/yielded.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/column/__init__.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/column/expressions.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/column/functions.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/column/sql.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/constants.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/dataframe/__init__.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/dataframe/api.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/dataframe/array_dataframe.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/dataframe/arrow_dataframe.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/dataframe/dataframe.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/dataframe/dataframe_iterable_dataframe.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/dataframe/dataframes.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/dataframe/function_wrapper.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/dataframe/iterable_dataframe.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/dataframe/pandas_dataframe.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/dataframe/utils.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/dataset/__init__.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/dataset/api.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/dataset/dataset.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/dev.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/exceptions.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/execution/__init__.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/execution/api.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/execution/execution_engine.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/execution/factory.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/execution/native_execution_engine.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/extensions/__init__.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/extensions/_builtins/__init__.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/extensions/_builtins/creators.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/extensions/_builtins/outputters.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/extensions/_builtins/processors.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/extensions/_utils.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/extensions/context.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/extensions/creator/__init__.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/extensions/creator/convert.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/extensions/creator/creator.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/extensions/outputter/__init__.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/extensions/outputter/convert.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/extensions/outputter/outputter.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/extensions/processor/__init__.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/extensions/processor/convert.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/extensions/processor/processor.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/extensions/transformer/__init__.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/extensions/transformer/constants.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/extensions/transformer/convert.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/extensions/transformer/transformer.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/plugins.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/py.typed +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/registry.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/rpc/__init__.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/rpc/base.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/rpc/flask.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/sql/__init__.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/sql/_utils.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/sql/_visitors.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/sql/api.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/sql/workflow.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/test/__init__.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/test/pandas_tester.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/test/plugins.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/workflow/__init__.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/workflow/_checkpoint.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/workflow/_tasks.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/workflow/_workflow_context.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/workflow/api.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/workflow/input.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/workflow/module.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue/workflow/workflow.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue.egg-info/SOURCES.txt +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue.egg-info/dependency_links.txt +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue.egg-info/entry_points.txt +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue.egg-info/requires.txt +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue.egg-info/top_level.txt +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_contrib/__init__.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_contrib/contrib.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_contrib/seaborn/__init__.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_contrib/viz/__init__.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_contrib/viz/_ext.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_dask/__init__.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_dask/_constants.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_dask/_dask_sql_wrapper.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_dask/_io.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_dask/_utils.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_dask/dataframe.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_dask/execution_engine.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_dask/registry.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_dask/tester.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_duckdb/__init__.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_duckdb/_io.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_duckdb/_utils.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_duckdb/dask.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_duckdb/dataframe.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_duckdb/execution_engine.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_duckdb/registry.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_duckdb/tester.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_ibis/__init__.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_ibis/_compat.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_ibis/_utils.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_ibis/dataframe.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_ibis/execution_engine.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_notebook/__init__.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_notebook/env.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_notebook/nbextension/README.md +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_notebook/nbextension/__init__.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_notebook/nbextension/description.yaml +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_notebook/nbextension/main.js +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_polars/__init__.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_polars/_utils.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_polars/polars_dataframe.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_polars/registry.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_ray/__init__.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_ray/_constants.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_ray/_utils/__init__.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_ray/_utils/cluster.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_ray/_utils/dataframe.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_ray/dataframe.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_ray/execution_engine.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_ray/registry.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_ray/tester.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_spark/__init__.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_spark/_constants.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_spark/_utils/__init__.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_spark/_utils/convert.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_spark/_utils/io.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_spark/_utils/partition.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_spark/dataframe.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_spark/registry.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_spark/tester.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_sql/__init__.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_sql/exceptions.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_test/__init__.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_test/bag_suite.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_test/builtin_suite.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_test/dataframe_suite.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_test/execution_suite.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/fugue_test/fixtures.py +0 -0
- {fugue-0.9.7.dev2 → fugue-0.9.8}/setup.cfg +0 -0
|
@@ -1,23 +1,22 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fugue
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.8
|
|
4
4
|
Summary: An abstraction layer for distributed computing
|
|
5
5
|
Author-email: The Fugue Development Team <hello@fugue.ai>
|
|
6
6
|
License: Apache-2.0
|
|
7
7
|
Project-URL: Homepage, http://github.com/fugue-project/fugue
|
|
8
8
|
Project-URL: Repository, http://github.com/fugue-project/fugue
|
|
9
|
-
Keywords: distributed,spark,dask,ray,sql,dsl,domain specific language
|
|
9
|
+
Keywords: distributed,spark,dask,ray,duckdb,sql,dsl,domain specific language
|
|
10
10
|
Classifier: Development Status :: 5 - Production/Stable
|
|
11
11
|
Classifier: Intended Audience :: Developers
|
|
12
12
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
13
13
|
Classifier: Programming Language :: Python :: 3
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
15
14
|
Classifier: Programming Language :: Python :: 3.11
|
|
16
15
|
Classifier: Programming Language :: Python :: 3.12
|
|
17
16
|
Classifier: Programming Language :: Python :: 3.13
|
|
18
17
|
Classifier: Programming Language :: Python :: 3.14
|
|
19
18
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
20
|
-
Requires-Python: >=3.
|
|
19
|
+
Requires-Python: >=3.11
|
|
21
20
|
Description-Content-Type: text/markdown
|
|
22
21
|
License-File: LICENSE
|
|
23
22
|
Requires-Dist: triad>=1.0.1
|
|
@@ -82,7 +81,7 @@ Dynamic: license-file
|
|
|
82
81
|
[](https://pypi.python.org/pypi/fugue/)
|
|
83
82
|
[](https://pypi.python.org/pypi/fugue/)
|
|
84
83
|
[](https://pypi.python.org/pypi/fugue/)
|
|
85
|
-
[](https://codecov.io/gh/fugue-project/fugue)
|
|
86
85
|
[](https://www.codacy.com/gh/fugue-project/fugue/dashboard?utm_source=github.com&utm_medium=referral&utm_content=fugue-project/fugue&utm_campaign=Badge_Grade)
|
|
87
86
|
[](https://pepy.tech/project/fugue)
|
|
88
87
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
[](https://pypi.python.org/pypi/fugue/)
|
|
4
4
|
[](https://pypi.python.org/pypi/fugue/)
|
|
5
5
|
[](https://pypi.python.org/pypi/fugue/)
|
|
6
|
-
[](https://codecov.io/gh/fugue-project/fugue)
|
|
7
7
|
[](https://www.codacy.com/gh/fugue-project/fugue/dashboard?utm_source=github.com&utm_medium=referral&utm_content=fugue-project/fugue&utm_campaign=Badge_Grade)
|
|
8
8
|
[](https://pepy.tech/project/fugue)
|
|
9
9
|
|
|
@@ -1,23 +1,22 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fugue
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.8
|
|
4
4
|
Summary: An abstraction layer for distributed computing
|
|
5
5
|
Author-email: The Fugue Development Team <hello@fugue.ai>
|
|
6
6
|
License: Apache-2.0
|
|
7
7
|
Project-URL: Homepage, http://github.com/fugue-project/fugue
|
|
8
8
|
Project-URL: Repository, http://github.com/fugue-project/fugue
|
|
9
|
-
Keywords: distributed,spark,dask,ray,sql,dsl,domain specific language
|
|
9
|
+
Keywords: distributed,spark,dask,ray,duckdb,sql,dsl,domain specific language
|
|
10
10
|
Classifier: Development Status :: 5 - Production/Stable
|
|
11
11
|
Classifier: Intended Audience :: Developers
|
|
12
12
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
13
13
|
Classifier: Programming Language :: Python :: 3
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
15
14
|
Classifier: Programming Language :: Python :: 3.11
|
|
16
15
|
Classifier: Programming Language :: Python :: 3.12
|
|
17
16
|
Classifier: Programming Language :: Python :: 3.13
|
|
18
17
|
Classifier: Programming Language :: Python :: 3.14
|
|
19
18
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
20
|
-
Requires-Python: >=3.
|
|
19
|
+
Requires-Python: >=3.11
|
|
21
20
|
Description-Content-Type: text/markdown
|
|
22
21
|
License-File: LICENSE
|
|
23
22
|
Requires-Dist: triad>=1.0.1
|
|
@@ -82,7 +81,7 @@ Dynamic: license-file
|
|
|
82
81
|
[](https://pypi.python.org/pypi/fugue/)
|
|
83
82
|
[](https://pypi.python.org/pypi/fugue/)
|
|
84
83
|
[](https://pypi.python.org/pypi/fugue/)
|
|
85
|
-
[](https://codecov.io/gh/fugue-project/fugue)
|
|
86
85
|
[](https://www.codacy.com/gh/fugue-project/fugue/dashboard?utm_source=github.com&utm_medium=referral&utm_content=fugue-project/fugue&utm_campaign=Badge_Grade)
|
|
87
86
|
[](https://pepy.tech/project/fugue)
|
|
88
87
|
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import pathlib
|
|
3
|
-
from
|
|
3
|
+
from collections.abc import Callable, Iterable
|
|
4
|
+
from typing import Any
|
|
4
5
|
|
|
5
6
|
import pyarrow as pa
|
|
6
7
|
import ray.data as rd
|
|
7
8
|
from packaging import version
|
|
8
9
|
from pyarrow import csv as pacsv
|
|
9
10
|
from pyarrow import json as pajson
|
|
10
|
-
|
|
11
11
|
from triad.collections import Schema
|
|
12
12
|
from triad.collections.dict import ParamDict
|
|
13
13
|
from triad.utils.assertion import assert_or_throw
|
|
14
|
-
from triad.utils.io import exists, makedirs, rm
|
|
14
|
+
from triad.utils.io import exists, isfile, makedirs, rm
|
|
15
15
|
|
|
16
16
|
from fugue import ExecutionEngine
|
|
17
17
|
from fugue._utils.io import FileParser, save_df
|
|
@@ -25,9 +25,7 @@ try:
|
|
|
25
25
|
from ray.data.datasource import FileExtensionFilter
|
|
26
26
|
|
|
27
27
|
class _FileFiler(FileExtensionFilter): # pragma: no cover
|
|
28
|
-
def __init__(
|
|
29
|
-
self, file_extensions: Union[str, List[str]], exclude: Iterable[str]
|
|
30
|
-
):
|
|
28
|
+
def __init__(self, file_extensions: str | list[str], exclude: Iterable[str]):
|
|
31
29
|
super().__init__(file_extensions, allow_if_no_extension=True)
|
|
32
30
|
self._exclude = set(exclude)
|
|
33
31
|
|
|
@@ -36,23 +34,23 @@ try:
|
|
|
36
34
|
path
|
|
37
35
|
).name not in self._exclude and self._file_has_extension(path)
|
|
38
36
|
|
|
39
|
-
def __call__(self, paths:
|
|
37
|
+
def __call__(self, paths: list[str]) -> list[str]:
|
|
40
38
|
return [path for path in paths if self._is_valid(path)]
|
|
41
39
|
|
|
42
40
|
except ImportError: # pragma: no cover
|
|
43
41
|
pass # ray >=2.10
|
|
44
42
|
|
|
45
43
|
|
|
46
|
-
class RayIO
|
|
44
|
+
class RayIO:
|
|
47
45
|
def __init__(self, engine: ExecutionEngine):
|
|
48
46
|
self._engine = engine
|
|
49
47
|
self._logger = engine.log
|
|
50
|
-
self._loads:
|
|
48
|
+
self._loads: dict[str, Callable[..., DataFrame]] = {
|
|
51
49
|
"csv": self._load_csv,
|
|
52
50
|
"parquet": self._load_parquet,
|
|
53
51
|
"json": self._load_json,
|
|
54
52
|
}
|
|
55
|
-
self._saves:
|
|
53
|
+
self._saves: dict[str, Callable[..., None]] = {
|
|
56
54
|
"csv": self._save_csv,
|
|
57
55
|
"parquet": self._save_parquet,
|
|
58
56
|
"json": self._save_json,
|
|
@@ -60,8 +58,8 @@ class RayIO(object):
|
|
|
60
58
|
|
|
61
59
|
def load_df(
|
|
62
60
|
self,
|
|
63
|
-
uri:
|
|
64
|
-
format_hint:
|
|
61
|
+
uri: str | list[str],
|
|
62
|
+
format_hint: str | None = None,
|
|
65
63
|
columns: Any = None,
|
|
66
64
|
**kwargs: Any,
|
|
67
65
|
) -> DataFrame:
|
|
@@ -81,8 +79,8 @@ class RayIO(object):
|
|
|
81
79
|
self,
|
|
82
80
|
df: RayDataFrame,
|
|
83
81
|
uri: str,
|
|
84
|
-
format_hint:
|
|
85
|
-
partition_spec:
|
|
82
|
+
format_hint: str | None = None,
|
|
83
|
+
partition_spec: PartitionSpec | None = None,
|
|
86
84
|
mode: str = "overwrite",
|
|
87
85
|
force_single: bool = False,
|
|
88
86
|
**kwargs: Any,
|
|
@@ -122,7 +120,7 @@ class RayIO(object):
|
|
|
122
120
|
if "header" in kw:
|
|
123
121
|
kw["include_header"] = kw.pop("header")
|
|
124
122
|
|
|
125
|
-
def _fn() ->
|
|
123
|
+
def _fn() -> dict[str, Any]: # pragma: no cover
|
|
126
124
|
return dict(write_options=pacsv.WriteOptions(**kw))
|
|
127
125
|
|
|
128
126
|
df.native.write_csv(
|
|
@@ -152,13 +150,25 @@ class RayIO(object):
|
|
|
152
150
|
)
|
|
153
151
|
|
|
154
152
|
def _load_parquet(
|
|
155
|
-
self, p:
|
|
153
|
+
self, p: list[str], columns: Any = None, **kwargs: Any
|
|
156
154
|
) -> DataFrame:
|
|
157
155
|
# in 2.52.0 the default changes to ["parquet"]
|
|
158
156
|
if "file_extensions" not in kwargs:
|
|
159
157
|
kwargs = kwargs.copy()
|
|
160
158
|
kwargs["file_extensions"] = None
|
|
161
|
-
|
|
159
|
+
# ray>=2.60 routes read_parquet to the V2 datasource by default, which
|
|
160
|
+
# (1) forces file_extensions=None to ["parquet"], so single files without
|
|
161
|
+
# extension can't be read, and (2) may raise ImportError from a threaded
|
|
162
|
+
# fsspec HTTPFileSystem import when listing multiple paths. Use V1.
|
|
163
|
+
ctx = rd.DataContext.get_current()
|
|
164
|
+
use_v2 = getattr(ctx, "use_datasource_v2", None)
|
|
165
|
+
if use_v2: # pragma: no cover
|
|
166
|
+
ctx.use_datasource_v2 = False
|
|
167
|
+
try:
|
|
168
|
+
sdf = rd.read_parquet(p, ray_remote_args=self._remote_args(), **kwargs)
|
|
169
|
+
finally:
|
|
170
|
+
if use_v2: # pragma: no cover
|
|
171
|
+
ctx.use_datasource_v2 = use_v2
|
|
162
172
|
if columns is None:
|
|
163
173
|
return RayDataFrame(sdf)
|
|
164
174
|
if isinstance(columns, list): # column names
|
|
@@ -166,20 +176,18 @@ class RayIO(object):
|
|
|
166
176
|
schema = Schema(columns)
|
|
167
177
|
return RayDataFrame(sdf)[schema.names].alter_columns(schema)
|
|
168
178
|
|
|
169
|
-
def _load_csv(
|
|
170
|
-
self, p: List[str], columns: Any = None, **kwargs: Any
|
|
171
|
-
) -> DataFrame:
|
|
179
|
+
def _load_csv(self, p: list[str], columns: Any = None, **kwargs: Any) -> DataFrame:
|
|
172
180
|
kw = ParamDict(kwargs)
|
|
173
181
|
infer_schema = kw.get("infer_schema", False)
|
|
174
|
-
read_options:
|
|
175
|
-
parse_options:
|
|
176
|
-
convert_options:
|
|
182
|
+
read_options: dict[str, Any] = {"use_threads": False}
|
|
183
|
+
parse_options: dict[str, Any] = {}
|
|
184
|
+
convert_options: dict[str, Any] = {}
|
|
177
185
|
if infer_schema and columns is not None and not isinstance(columns, list):
|
|
178
186
|
raise ValueError("can't set columns as a schema when infer schema is true")
|
|
179
187
|
|
|
180
188
|
if RAY_VERSION >= version.parse("2.10"):
|
|
181
189
|
if len(p) == 1 and isfile(p[0]): # TODO: very hacky
|
|
182
|
-
params:
|
|
190
|
+
params: dict[str, Any] = {}
|
|
183
191
|
else:
|
|
184
192
|
params = {"file_extensions": ["csv"]}
|
|
185
193
|
else: # pragma: no cover
|
|
@@ -230,14 +238,14 @@ class RayIO(object):
|
|
|
230
238
|
else: # pragma: no cover
|
|
231
239
|
raise NotImplementedError(f"{header} is not supported")
|
|
232
240
|
|
|
233
|
-
def _load_json(self, p:
|
|
234
|
-
read_options:
|
|
235
|
-
parse_options:
|
|
241
|
+
def _load_json(self, p: list[str], columns: Any = None, **kwargs: Any) -> DataFrame:
|
|
242
|
+
read_options: dict[str, Any] = {"use_threads": False}
|
|
243
|
+
parse_options: dict[str, Any] = {}
|
|
236
244
|
|
|
237
245
|
def _read_json() -> RayDataFrame: # pragma: no cover
|
|
238
246
|
if RAY_VERSION >= version.parse("2.10"):
|
|
239
247
|
if len(p) == 1 and isfile(p[0]): # TODO: very hacky
|
|
240
|
-
params:
|
|
248
|
+
params: dict[str, Any] = {"file_extensions": None}
|
|
241
249
|
else:
|
|
242
250
|
params = {"file_extensions": ["json"]}
|
|
243
251
|
elif RAY_VERSION >= version.parse("2.9"): # pragma: no cover
|
|
@@ -272,5 +280,5 @@ class RayIO(object):
|
|
|
272
280
|
schema = Schema(columns)
|
|
273
281
|
return _read_json()[schema.names].alter_columns(schema)
|
|
274
282
|
|
|
275
|
-
def _remote_args(self) ->
|
|
283
|
+
def _remote_args(self) -> dict[str, Any]:
|
|
276
284
|
return {"num_cpus": 1}
|
|
@@ -1,25 +1,23 @@
|
|
|
1
1
|
import pyspark.sql as ps
|
|
2
|
-
import pyspark
|
|
3
2
|
from typing import Any
|
|
4
3
|
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
try:
|
|
6
|
+
from pyspark.sql import is_remote as _is_remote
|
|
7
|
+
except ImportError: # pragma: no cover
|
|
8
|
+
_is_remote = None
|
|
7
9
|
|
|
8
10
|
try:
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
from pyspark.sql import DataFrame as SparkConnectDataFrame
|
|
12
|
-
else: # pragma: no cover
|
|
13
|
-
from pyspark.sql.connect.session import SparkSession as SparkConnectSession
|
|
14
|
-
from pyspark.sql.connect.dataframe import DataFrame as SparkConnectDataFrame
|
|
11
|
+
from pyspark.sql.connect.session import SparkSession as SparkConnectSession
|
|
12
|
+
from pyspark.sql.connect.dataframe import DataFrame as SparkConnectDataFrame
|
|
15
13
|
except Exception: # pragma: no cover
|
|
16
14
|
SparkConnectSession = None
|
|
17
15
|
SparkConnectDataFrame = None
|
|
18
16
|
|
|
19
17
|
|
|
20
18
|
def is_spark_connect(session: Any) -> bool: # pragma: no cover
|
|
21
|
-
if
|
|
22
|
-
return
|
|
19
|
+
if _is_remote is not None:
|
|
20
|
+
return _is_remote()
|
|
23
21
|
return SparkConnectSession is not None and isinstance(
|
|
24
22
|
session, (SparkConnectSession, SparkConnectDataFrame)
|
|
25
23
|
)
|
|
@@ -403,10 +403,17 @@ class SparkExecutionEngine(ExecutionEngine):
|
|
|
403
403
|
def get_current_parallelism(self) -> int:
|
|
404
404
|
spark = self.spark_session
|
|
405
405
|
if self.is_spark_connect: # pragma: no cover
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
406
|
+
for key in (
|
|
407
|
+
"spark.default.parallelism",
|
|
408
|
+
"spark.sql.shuffle.partitions",
|
|
409
|
+
):
|
|
410
|
+
try:
|
|
411
|
+
value = spark.conf.get(key, "")
|
|
412
|
+
except Exception:
|
|
413
|
+
continue
|
|
414
|
+
if value != "":
|
|
415
|
+
return int(value)
|
|
416
|
+
return 200
|
|
410
417
|
e_cores = int(spark.conf.get("spark.executor.cores", "1"))
|
|
411
418
|
tc = int(spark.conf.get("spark.task.cpus", "1"))
|
|
412
419
|
sc = spark._jsc.sc()
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "fugue"
|
|
7
|
-
version = "0.9.
|
|
7
|
+
version = "0.9.8"
|
|
8
8
|
description = "An abstraction layer for distributed computing"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "Apache-2.0" }
|
|
@@ -14,6 +14,7 @@ keywords = [
|
|
|
14
14
|
"spark",
|
|
15
15
|
"dask",
|
|
16
16
|
"ray",
|
|
17
|
+
"duckdb",
|
|
17
18
|
"sql",
|
|
18
19
|
"dsl",
|
|
19
20
|
"domain specific language",
|
|
@@ -23,14 +24,13 @@ classifiers = [
|
|
|
23
24
|
"Intended Audience :: Developers",
|
|
24
25
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
25
26
|
"Programming Language :: Python :: 3",
|
|
26
|
-
"Programming Language :: Python :: 3.10",
|
|
27
27
|
"Programming Language :: Python :: 3.11",
|
|
28
28
|
"Programming Language :: Python :: 3.12",
|
|
29
29
|
"Programming Language :: Python :: 3.13",
|
|
30
30
|
"Programming Language :: Python :: 3.14",
|
|
31
31
|
"Programming Language :: Python :: 3 :: Only",
|
|
32
32
|
]
|
|
33
|
-
requires-python = ">=3.
|
|
33
|
+
requires-python = ">=3.11"
|
|
34
34
|
dependencies = ["triad>=1.0.1", "adagio>=0.2.6", "pandas<3"]
|
|
35
35
|
|
|
36
36
|
[project.urls]
|
|
@@ -114,6 +114,7 @@ dev = [
|
|
|
114
114
|
"s3fs",
|
|
115
115
|
# Specific versions for compatibility
|
|
116
116
|
"pyspark[connect]",
|
|
117
|
+
"pyarrow<23", # pyarrow>=23 needs numpy>=2; pyspark 3.x pins numpy<2
|
|
117
118
|
"duckdb-engine>=0.6.4",
|
|
118
119
|
"sqlalchemy==2.0.10",
|
|
119
120
|
"ray[data]>=2.30.0; python_version<'3.14'",
|
|
@@ -202,7 +203,7 @@ max-complexity = 10
|
|
|
202
203
|
[tool.tox]
|
|
203
204
|
legacy_tox_ini = """
|
|
204
205
|
[tox]
|
|
205
|
-
envlist =
|
|
206
|
+
envlist = py311,py312,py313,py314
|
|
206
207
|
|
|
207
208
|
[testenv]
|
|
208
209
|
setenv =
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|