apache-hamilton 1.90.0.dev0__py3-none-any.whl

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 (151) hide show
  1. apache_hamilton-1.90.0.dev0.dist-info/METADATA +407 -0
  2. apache_hamilton-1.90.0.dev0.dist-info/RECORD +151 -0
  3. apache_hamilton-1.90.0.dev0.dist-info/WHEEL +4 -0
  4. apache_hamilton-1.90.0.dev0.dist-info/entry_points.txt +9 -0
  5. apache_hamilton-1.90.0.dev0.dist-info/licenses/DISCLAIMER +10 -0
  6. apache_hamilton-1.90.0.dev0.dist-info/licenses/LICENSE +228 -0
  7. apache_hamilton-1.90.0.dev0.dist-info/licenses/NOTICE +5 -0
  8. hamilton/__init__.py +24 -0
  9. hamilton/ad_hoc_utils.py +132 -0
  10. hamilton/async_driver.py +465 -0
  11. hamilton/base.py +466 -0
  12. hamilton/caching/__init__.py +16 -0
  13. hamilton/caching/adapter.py +1475 -0
  14. hamilton/caching/cache_key.py +70 -0
  15. hamilton/caching/fingerprinting.py +287 -0
  16. hamilton/caching/stores/__init__.py +16 -0
  17. hamilton/caching/stores/base.py +242 -0
  18. hamilton/caching/stores/file.py +140 -0
  19. hamilton/caching/stores/memory.py +297 -0
  20. hamilton/caching/stores/sqlite.py +282 -0
  21. hamilton/caching/stores/utils.py +40 -0
  22. hamilton/cli/__init__.py +16 -0
  23. hamilton/cli/__main__.py +328 -0
  24. hamilton/cli/commands.py +126 -0
  25. hamilton/cli/logic.py +338 -0
  26. hamilton/common/__init__.py +76 -0
  27. hamilton/contrib/__init__.py +41 -0
  28. hamilton/data_quality/__init__.py +16 -0
  29. hamilton/data_quality/base.py +198 -0
  30. hamilton/data_quality/default_validators.py +560 -0
  31. hamilton/data_quality/pandera_validators.py +121 -0
  32. hamilton/dataflows/__init__.py +726 -0
  33. hamilton/dataflows/template/README.md +25 -0
  34. hamilton/dataflows/template/__init__.py +54 -0
  35. hamilton/dataflows/template/author.md +28 -0
  36. hamilton/dataflows/template/requirements.txt +0 -0
  37. hamilton/dataflows/template/tags.json +7 -0
  38. hamilton/dataflows/template/valid_configs.jsonl +1 -0
  39. hamilton/dev_utils/__init__.py +16 -0
  40. hamilton/dev_utils/deprecation.py +204 -0
  41. hamilton/driver.py +2112 -0
  42. hamilton/execution/__init__.py +16 -0
  43. hamilton/execution/debugging_utils.py +56 -0
  44. hamilton/execution/executors.py +502 -0
  45. hamilton/execution/graph_functions.py +421 -0
  46. hamilton/execution/grouping.py +430 -0
  47. hamilton/execution/state.py +539 -0
  48. hamilton/experimental/__init__.py +27 -0
  49. hamilton/experimental/databackend.py +61 -0
  50. hamilton/experimental/decorators/__init__.py +16 -0
  51. hamilton/experimental/decorators/parameterize_frame.py +233 -0
  52. hamilton/experimental/h_async.py +29 -0
  53. hamilton/experimental/h_cache.py +413 -0
  54. hamilton/experimental/h_dask.py +28 -0
  55. hamilton/experimental/h_databackends.py +174 -0
  56. hamilton/experimental/h_ray.py +28 -0
  57. hamilton/experimental/h_spark.py +32 -0
  58. hamilton/function_modifiers/README +40 -0
  59. hamilton/function_modifiers/__init__.py +121 -0
  60. hamilton/function_modifiers/adapters.py +900 -0
  61. hamilton/function_modifiers/base.py +859 -0
  62. hamilton/function_modifiers/configuration.py +310 -0
  63. hamilton/function_modifiers/delayed.py +202 -0
  64. hamilton/function_modifiers/dependencies.py +246 -0
  65. hamilton/function_modifiers/expanders.py +1230 -0
  66. hamilton/function_modifiers/macros.py +1634 -0
  67. hamilton/function_modifiers/metadata.py +434 -0
  68. hamilton/function_modifiers/recursive.py +908 -0
  69. hamilton/function_modifiers/validation.py +289 -0
  70. hamilton/function_modifiers_base.py +31 -0
  71. hamilton/graph.py +1153 -0
  72. hamilton/graph_types.py +264 -0
  73. hamilton/graph_utils.py +41 -0
  74. hamilton/htypes.py +450 -0
  75. hamilton/io/__init__.py +32 -0
  76. hamilton/io/data_adapters.py +216 -0
  77. hamilton/io/default_data_loaders.py +224 -0
  78. hamilton/io/materialization.py +500 -0
  79. hamilton/io/utils.py +158 -0
  80. hamilton/lifecycle/__init__.py +67 -0
  81. hamilton/lifecycle/api.py +833 -0
  82. hamilton/lifecycle/base.py +1130 -0
  83. hamilton/lifecycle/default.py +802 -0
  84. hamilton/log_setup.py +47 -0
  85. hamilton/models.py +92 -0
  86. hamilton/node.py +449 -0
  87. hamilton/plugins/README.md +48 -0
  88. hamilton/plugins/__init__.py +16 -0
  89. hamilton/plugins/dask_extensions.py +47 -0
  90. hamilton/plugins/dlt_extensions.py +161 -0
  91. hamilton/plugins/geopandas_extensions.py +49 -0
  92. hamilton/plugins/h_dask.py +331 -0
  93. hamilton/plugins/h_ddog.py +522 -0
  94. hamilton/plugins/h_diskcache.py +163 -0
  95. hamilton/plugins/h_experiments/__init__.py +22 -0
  96. hamilton/plugins/h_experiments/__main__.py +62 -0
  97. hamilton/plugins/h_experiments/cache.py +39 -0
  98. hamilton/plugins/h_experiments/data_model.py +68 -0
  99. hamilton/plugins/h_experiments/hook.py +219 -0
  100. hamilton/plugins/h_experiments/server.py +375 -0
  101. hamilton/plugins/h_kedro.py +152 -0
  102. hamilton/plugins/h_logging.py +454 -0
  103. hamilton/plugins/h_mcp/__init__.py +28 -0
  104. hamilton/plugins/h_mcp/__main__.py +33 -0
  105. hamilton/plugins/h_mcp/_helpers.py +129 -0
  106. hamilton/plugins/h_mcp/_templates.py +417 -0
  107. hamilton/plugins/h_mcp/server.py +328 -0
  108. hamilton/plugins/h_mlflow.py +335 -0
  109. hamilton/plugins/h_narwhals.py +134 -0
  110. hamilton/plugins/h_openlineage.py +400 -0
  111. hamilton/plugins/h_opentelemetry.py +167 -0
  112. hamilton/plugins/h_pandas.py +257 -0
  113. hamilton/plugins/h_pandera.py +117 -0
  114. hamilton/plugins/h_polars.py +304 -0
  115. hamilton/plugins/h_polars_lazyframe.py +282 -0
  116. hamilton/plugins/h_pyarrow.py +56 -0
  117. hamilton/plugins/h_pydantic.py +127 -0
  118. hamilton/plugins/h_ray.py +242 -0
  119. hamilton/plugins/h_rich.py +142 -0
  120. hamilton/plugins/h_schema.py +493 -0
  121. hamilton/plugins/h_slack.py +100 -0
  122. hamilton/plugins/h_spark.py +1380 -0
  123. hamilton/plugins/h_threadpool.py +125 -0
  124. hamilton/plugins/h_tqdm.py +122 -0
  125. hamilton/plugins/h_vaex.py +129 -0
  126. hamilton/plugins/huggingface_extensions.py +236 -0
  127. hamilton/plugins/ibis_extensions.py +93 -0
  128. hamilton/plugins/jupyter_magic.py +622 -0
  129. hamilton/plugins/kedro_extensions.py +117 -0
  130. hamilton/plugins/lightgbm_extensions.py +99 -0
  131. hamilton/plugins/matplotlib_extensions.py +108 -0
  132. hamilton/plugins/mlflow_extensions.py +216 -0
  133. hamilton/plugins/numpy_extensions.py +105 -0
  134. hamilton/plugins/pandas_extensions.py +1763 -0
  135. hamilton/plugins/plotly_extensions.py +150 -0
  136. hamilton/plugins/polars_extensions.py +71 -0
  137. hamilton/plugins/polars_implementations.py +25 -0
  138. hamilton/plugins/polars_lazyframe_extensions.py +302 -0
  139. hamilton/plugins/polars_post_1_0_0_extensions.py +877 -0
  140. hamilton/plugins/polars_pre_1_0_0_extension.py +836 -0
  141. hamilton/plugins/pydantic_extensions.py +98 -0
  142. hamilton/plugins/pyspark_pandas_extensions.py +47 -0
  143. hamilton/plugins/sklearn_plot_extensions.py +129 -0
  144. hamilton/plugins/spark_extensions.py +105 -0
  145. hamilton/plugins/vaex_extensions.py +51 -0
  146. hamilton/plugins/xgboost_extensions.py +91 -0
  147. hamilton/plugins/yaml_extensions.py +89 -0
  148. hamilton/registry.py +254 -0
  149. hamilton/settings.py +18 -0
  150. hamilton/telemetry.py +50 -0
  151. hamilton/version.py +18 -0
@@ -0,0 +1,150 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one
2
+ # or more contributor license agreements. See the NOTICE file
3
+ # distributed with this work for additional information
4
+ # regarding copyright ownership. The ASF licenses this file
5
+ # to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance
7
+ # with the License. You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ import dataclasses
19
+ import pathlib
20
+ from collections.abc import Collection
21
+ from typing import IO, Any
22
+
23
+ try:
24
+ import plotly.graph_objects
25
+ except ImportError as e:
26
+ raise NotImplementedError("Plotly is not installed.") from e
27
+
28
+ from hamilton import registry
29
+ from hamilton.io import utils
30
+ from hamilton.io.data_adapters import DataSaver
31
+
32
+
33
+ @dataclasses.dataclass
34
+ class PlotlyStaticWriter(DataSaver):
35
+ """Write Plotly figure as static image format
36
+ ref: https://plotly.com/python/static-image-export/
37
+ """
38
+
39
+ path: str | pathlib.Path | IO
40
+ format: str | None = None
41
+ width: int | None = None
42
+ height: int | None = None
43
+ scale: int | float | None = None
44
+ validate: bool = True
45
+ engine: str = "auto"
46
+
47
+ def _get_saving_kwargs(self) -> dict:
48
+ kwargs = {}
49
+ if self.format is not None:
50
+ kwargs["format"] = self.format
51
+ if self.width is not None:
52
+ kwargs["width"] = self.width
53
+ if self.height is not None:
54
+ kwargs["height"] = self.height
55
+ if self.scale is not None:
56
+ kwargs["scale"] = self.scale
57
+ if self.validate is not None:
58
+ kwargs["validate"] = self.validate
59
+ if self.engine is not None:
60
+ kwargs["engine"] = self.engine
61
+
62
+ return kwargs
63
+
64
+ def save_data(self, data: plotly.graph_objects.Figure) -> dict[str, Any]:
65
+ data.write_image(file=self.path, **self._get_saving_kwargs())
66
+ return utils.get_file_metadata(self.path)
67
+
68
+ @classmethod
69
+ def applicable_types(cls) -> Collection[type]:
70
+ return [plotly.graph_objects.Figure]
71
+
72
+ @classmethod
73
+ def name(cls) -> str:
74
+ return "plotly"
75
+
76
+
77
+ @dataclasses.dataclass
78
+ class PlotlyInteractiveWriter(DataSaver):
79
+ """Write Plotly figure as interactive HTML + JS
80
+ ref: https://plotly.com/python/interactive-html-export/
81
+ """
82
+
83
+ path: str | pathlib.Path | IO
84
+ config: dict | None = None
85
+ auto_play: bool = True
86
+ include_plotlyjs: bool | str = (
87
+ True # or "cdn", "directory", "require", "False", "other string .js"
88
+ )
89
+ include_mathjax: bool | str = False # "cdn", "string .js"
90
+ post_script: str | list[str] | None = None
91
+ full_html: bool = True
92
+ animation_opts: dict | None = None
93
+ default_width: int | float | str = "100%"
94
+ default_height: int | float | str = "100%"
95
+ validate: bool = True
96
+ auto_open: bool = True
97
+ div_id: str | None = None
98
+
99
+ def _get_saving_kwargs(self) -> dict:
100
+ kwargs = {}
101
+ if self.config is not None:
102
+ kwargs["config"] = self.config
103
+ if self.auto_play is not None:
104
+ kwargs["auto_play"] = self.auto_play
105
+ if self.include_plotlyjs is not None:
106
+ kwargs["include_plotlyjs"] = self.include_plotlyjs
107
+ if self.include_mathjax is not None:
108
+ kwargs["include_mathjax"] = self.include_mathjax
109
+ if self.post_script is not None:
110
+ kwargs["post_script"] = self.post_script
111
+ if self.full_html is not None:
112
+ kwargs["full_html"] = self.full_html
113
+ if self.animation_opts is not None:
114
+ kwargs["animation_opts"] = self.animation_opts
115
+ if self.default_width is not None:
116
+ kwargs["default_width"] = self.default_width
117
+ if self.default_height is not None:
118
+ kwargs["default_height"] = self.default_height
119
+ if self.validate is not None:
120
+ kwargs["validate"] = self.validate
121
+ if self.auto_open is not None:
122
+ kwargs["auto_open"] = self.auto_open
123
+ if self.div_id is not None:
124
+ kwargs["div_id"] = self.div_id
125
+ return kwargs
126
+
127
+ def save_data(self, data: plotly.graph_objects.Figure) -> dict[str, Any]:
128
+ data.write_html(file=self.path, **self._get_saving_kwargs())
129
+ return utils.get_file_metadata(self.path)
130
+
131
+ @classmethod
132
+ def applicable_types(cls) -> Collection[type]:
133
+ return [plotly.graph_objects.Figure]
134
+
135
+ @classmethod
136
+ def name(cls) -> str:
137
+ return "html"
138
+
139
+
140
+ def register_data_loaders():
141
+ for loader in [
142
+ PlotlyStaticWriter,
143
+ PlotlyInteractiveWriter,
144
+ ]:
145
+ registry.register_adapter(loader)
146
+
147
+
148
+ register_data_loaders()
149
+
150
+ COLUMN_FRIENDLY_DF_TYPE = False
@@ -0,0 +1,71 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one
2
+ # or more contributor license agreements. See the NOTICE file
3
+ # distributed with this work for additional information
4
+ # regarding copyright ownership. The ASF licenses this file
5
+ # to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance
7
+ # with the License. You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ import logging
19
+ from typing import Any
20
+
21
+ from packaging import version
22
+
23
+ from hamilton import registry
24
+
25
+ logger = logging.getLogger(__name__)
26
+
27
+ try:
28
+ from xlsxwriter.workbook import Workbook
29
+ except ImportError:
30
+ Workbook = type
31
+
32
+ try:
33
+ import polars as pl
34
+ except ImportError as e:
35
+ raise NotImplementedError("Polars is not installed.") from e
36
+
37
+ pl_version = version.Version(pl.__version__)
38
+ if pl_version < version.Version("1.0.0"):
39
+ from hamilton.plugins.polars_pre_1_0_0_extension import register_data_loaders
40
+
41
+ logger.warning(
42
+ "Using pre-1.0.0 Polars integration -- we will stop supporting this in Hamilton 2.0, so please upgrade your version of polars! "
43
+ f"Current version: {pl_version}, minimum required version: 1.0.0."
44
+ )
45
+ else:
46
+ from hamilton.plugins.polars_post_1_0_0_extensions import register_data_loaders
47
+
48
+ register_data_loaders()
49
+
50
+ DATAFRAME_TYPE = pl.DataFrame
51
+ COLUMN_TYPE = pl.Series
52
+
53
+
54
+ def register_types():
55
+ """Function to register the types for this extension."""
56
+ registry.register_types("polars", DATAFRAME_TYPE, COLUMN_TYPE)
57
+
58
+
59
+ @registry.get_column.register(pl.DataFrame)
60
+ def get_column_polars(df: pl.DataFrame, column_name: str) -> pl.Series:
61
+ return df[column_name]
62
+
63
+
64
+ @registry.fill_with_scalar.register(pl.DataFrame)
65
+ def fill_with_scalar_polars(df: pl.DataFrame, column_name: str, scalar_value: Any) -> pl.DataFrame:
66
+ if not isinstance(scalar_value, pl.Series):
67
+ scalar_value = [scalar_value]
68
+ return df.with_columns(pl.Series(name=column_name, values=scalar_value))
69
+
70
+
71
+ register_types()
@@ -0,0 +1,25 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one
2
+ # or more contributor license agreements. See the NOTICE file
3
+ # distributed with this work for additional information
4
+ # regarding copyright ownership. The ASF licenses this file
5
+ # to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance
7
+ # with the License. You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ import logging
19
+
20
+ from hamilton.plugins.h_polars import PolarsDataFrameResult
21
+
22
+ logger = logging.getLogger(__name__)
23
+ logger.warning("This module is deprecated. Please use hamilton.plugins.h_polars instead.")
24
+
25
+ __all__ = ["PolarsDataFrameResult"]
@@ -0,0 +1,302 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one
2
+ # or more contributor license agreements. See the NOTICE file
3
+ # distributed with this work for additional information
4
+ # regarding copyright ownership. The ASF licenses this file
5
+ # to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance
7
+ # with the License. You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ import dataclasses
19
+ from collections.abc import Collection, Mapping, Sequence
20
+ from io import BytesIO
21
+ from pathlib import Path
22
+ from typing import (
23
+ Any,
24
+ BinaryIO,
25
+ TextIO,
26
+ )
27
+
28
+ try:
29
+ import polars as pl
30
+ except ImportError as e:
31
+ raise NotImplementedError("Polars is not installed.") from e
32
+
33
+
34
+ # for polars <0.16.0 we need to determine whether type_aliases exist.
35
+ has_alias = False
36
+ if hasattr(pl, "type_aliases"):
37
+ has_alias = True
38
+
39
+ # for polars 0.18.0 we need to check what to do.
40
+ if has_alias and hasattr(pl.type_aliases, "CsvEncoding"):
41
+ from polars.type_aliases import CsvEncoding
42
+ else:
43
+ CsvEncoding = type
44
+
45
+ # import these types to make type hinting work
46
+ from polars.datatypes import DataType, DataTypeClass # noqa: F401
47
+
48
+ from hamilton import registry
49
+ from hamilton.io import utils
50
+ from hamilton.io.data_adapters import DataLoader
51
+
52
+ DATAFRAME_TYPE = pl.LazyFrame
53
+ COLUMN_TYPE = pl.Expr
54
+ # COLUMN_FRIENDLY_DF_TYPE = False
55
+
56
+
57
+ def register_types():
58
+ """Function to register the types for this extension."""
59
+ registry.register_types("polars_lazyframe", DATAFRAME_TYPE, COLUMN_TYPE)
60
+
61
+
62
+ @registry.get_column.register(pl.LazyFrame)
63
+ def get_column_polars_lazyframe(df: pl.LazyFrame, column_name: str) -> pl.Expr:
64
+ # TODO: figure out if we can validate this here already or need to wait to the end
65
+ # when query.collect() resolves the lazy frame
66
+ # df.collect_schema().names() gives a list of names but it can be expensive
67
+ # https://docs.pola.rs/api/python/stable/reference/lazyframe/api/polars.LazyFrame.columns.html
68
+ # https://docs.pola.rs/api/python/stable/reference/lazyframe/api/polars.LazyFrame.collect_schema.html#polars.LazyFrame.collect_schema
69
+ return pl.col(column_name)
70
+
71
+
72
+ @registry.fill_with_scalar.register(pl.LazyFrame)
73
+ def fill_with_scalar_polars_lazyframe(
74
+ df: pl.LazyFrame, column_name: str, scalar_value: Any
75
+ ) -> pl.LazyFrame:
76
+ if not isinstance(scalar_value, pl.Expr):
77
+ scalar_value = pl.lit(scalar_value)
78
+ return df.with_columns(scalar_value.alias(column_name))
79
+
80
+
81
+ register_types()
82
+
83
+
84
+ @dataclasses.dataclass
85
+ class PolarsScanCSVReader(DataLoader):
86
+ """Class specifically to handle loading CSV files with Polars.
87
+ Should map to https://pola-rs.github.io/polars/py-polars/html/reference/api/polars.read_csv.html
88
+ """
89
+
90
+ file: str | TextIO | BytesIO | Path | BinaryIO | bytes
91
+ # kwargs:
92
+ has_header: bool = True
93
+ columns: Sequence[int] | Sequence[str] = None
94
+ new_columns: Sequence[str] = None
95
+ separator: str = ","
96
+ comment_char: str = None
97
+ quote_char: str = '"'
98
+ skip_rows: int = 0
99
+ dtypes: Mapping[str, Any] | Sequence[Any] = None
100
+ null_values: str | Sequence[str] | dict[str, str] = None
101
+ missing_utf8_is_empty_string: bool = False
102
+ ignore_errors: bool = False
103
+ try_parse_dates: bool = False
104
+ n_threads: int = None
105
+ infer_schema_length: int = 100
106
+ batch_size: int = 8192
107
+ n_rows: int = None
108
+ encoding: CsvEncoding | str = "utf8"
109
+ low_memory: bool = False
110
+ rechunk: bool = True
111
+ use_pyarrow: bool = False
112
+ storage_options: dict[str, Any] = None
113
+ skip_rows_after_header: int = 0
114
+ row_count_name: str = None
115
+ row_count_offset: int = 0
116
+ eol_char: str = "\n"
117
+ raise_if_empty: bool = True
118
+
119
+ def _get_loading_kwargs(self):
120
+ kwargs = {}
121
+ if self.has_header is not None:
122
+ kwargs["has_header"] = self.has_header
123
+ if self.columns is not None:
124
+ kwargs["columns"] = self.columns
125
+ if self.new_columns is not None:
126
+ kwargs["new_columns"] = self.new_columns
127
+ if self.separator is not None:
128
+ kwargs["separator"] = self.separator
129
+ if self.comment_char is not None:
130
+ kwargs["comment_char"] = self.comment_char
131
+ if self.quote_char is not None:
132
+ kwargs["quote_char"] = self.quote_char
133
+ if self.skip_rows is not None:
134
+ kwargs["skip_rows"] = self.skip_rows
135
+ if self.dtypes is not None:
136
+ kwargs["dtypes"] = self.dtypes
137
+ if self.null_values is not None:
138
+ kwargs["null_values"] = self.null_values
139
+ if self.missing_utf8_is_empty_string is not None:
140
+ kwargs["missing_utf8_is_empty_string"] = self.missing_utf8_is_empty_string
141
+ if self.ignore_errors is not None:
142
+ kwargs["ignore_errors"] = self.ignore_errors
143
+ if self.try_parse_dates is not None:
144
+ kwargs["try_parse_dates"] = self.try_parse_dates
145
+ if self.n_threads is not None:
146
+ kwargs["n_threads"] = self.n_threads
147
+ if self.infer_schema_length is not None:
148
+ kwargs["infer_schema_length"] = self.infer_schema_length
149
+ if self.n_rows is not None:
150
+ kwargs["n_rows"] = self.n_rows
151
+ if self.encoding is not None:
152
+ kwargs["encoding"] = self.encoding
153
+ if self.low_memory is not None:
154
+ kwargs["low_memory"] = self.low_memory
155
+ if self.rechunk is not None:
156
+ kwargs["rechunk"] = self.rechunk
157
+ if self.storage_options is not None:
158
+ kwargs["storage_options"] = self.storage_options
159
+ if self.skip_rows_after_header is not None:
160
+ kwargs["skip_rows_after_header"] = self.skip_rows_after_header
161
+ if self.row_count_name is not None:
162
+ kwargs["row_count_name"] = self.row_count_name
163
+ if self.row_count_offset is not None:
164
+ kwargs["row_count_offset"] = self.row_count_offset
165
+ if self.eol_char is not None:
166
+ kwargs["eol_char"] = self.eol_char
167
+ if self.raise_if_empty is not None:
168
+ kwargs["raise_if_empty"] = self.raise_if_empty
169
+ return kwargs
170
+
171
+ @classmethod
172
+ def applicable_types(cls) -> Collection[type]:
173
+ return [DATAFRAME_TYPE]
174
+
175
+ def load_data(self, type_: type) -> tuple[DATAFRAME_TYPE, dict[str, Any]]:
176
+ df = pl.scan_csv(self.file, **self._get_loading_kwargs())
177
+
178
+ metadata = utils.get_file_and_dataframe_metadata(self.file, df)
179
+ return df, metadata
180
+
181
+ @classmethod
182
+ def name(cls) -> str:
183
+ return "csv"
184
+
185
+
186
+ @dataclasses.dataclass
187
+ class PolarsScanParquetReader(DataLoader):
188
+ """Class specifically to handle loading parquet files with polars
189
+ Should map to https://pola-rs.github.io/polars/py-polars/html/reference/api/polars.read_parquet.html
190
+ """
191
+
192
+ file: str | TextIO | BytesIO | Path | BinaryIO | bytes
193
+ # kwargs:
194
+ columns: list[int] | list[str] = None
195
+ n_rows: int = None
196
+ use_pyarrow: bool = False
197
+ memory_map: bool = True
198
+ storage_options: dict[str, Any] = None
199
+ parallel: Any = "auto"
200
+ row_count_name: str = None
201
+ row_count_offset: int = 0
202
+ low_memory: bool = False
203
+ use_statistics: bool = True
204
+ rechunk: bool = True
205
+
206
+ @classmethod
207
+ def applicable_types(cls) -> Collection[type]:
208
+ return [DATAFRAME_TYPE]
209
+
210
+ def _get_loading_kwargs(self):
211
+ kwargs = {}
212
+ if self.columns is not None:
213
+ kwargs["columns"] = self.columns
214
+ if self.n_rows is not None:
215
+ kwargs["n_rows"] = self.n_rows
216
+ if self.storage_options is not None:
217
+ kwargs["storage_options"] = self.storage_options
218
+ if self.parallel is not None:
219
+ kwargs["parallel"] = self.parallel
220
+ if self.row_count_name is not None:
221
+ kwargs["row_count_name"] = self.row_count_name
222
+ if self.row_count_offset is not None:
223
+ kwargs["row_count_offset"] = self.row_count_offset
224
+ if self.low_memory is not None:
225
+ kwargs["low_memory"] = self.low_memory
226
+ if self.use_statistics is not None:
227
+ kwargs["use_statistics"] = self.use_statistics
228
+ if self.rechunk is not None:
229
+ kwargs["rechunk"] = self.rechunk
230
+ return kwargs
231
+
232
+ def load_data(self, type_: type) -> tuple[DATAFRAME_TYPE, dict[str, Any]]:
233
+ df = pl.scan_parquet(self.file, **self._get_loading_kwargs())
234
+ metadata = utils.get_file_and_dataframe_metadata(self.file, df)
235
+ return df, metadata
236
+
237
+ @classmethod
238
+ def name(cls) -> str:
239
+ return "parquet"
240
+
241
+
242
+ @dataclasses.dataclass
243
+ class PolarsScanFeatherReader(DataLoader):
244
+ """
245
+ Class specifically to handle loading Feather/Arrow IPC files with Polars.
246
+ Should map to https://pola-rs.github.io/polars/py-polars/html/reference/api/polars.read_ipc.html
247
+ """
248
+
249
+ source: str | BinaryIO | BytesIO | Path | bytes
250
+ # kwargs:
251
+ columns: list[str] | list[int] | None = None
252
+ n_rows: int | None = None
253
+ use_pyarrow: bool = False
254
+ memory_map: bool = True
255
+ storage_options: dict[str, Any] | None = None
256
+ row_count_name: str | None = None
257
+ row_count_offset: int = 0
258
+ rechunk: bool = True
259
+
260
+ @classmethod
261
+ def applicable_types(cls) -> Collection[type]:
262
+ return [DATAFRAME_TYPE]
263
+
264
+ def _get_loading_kwargs(self):
265
+ kwargs = {}
266
+ if self.columns is not None:
267
+ kwargs["columns"] = self.columns
268
+ if self.n_rows is not None:
269
+ kwargs["n_rows"] = self.n_rows
270
+ if self.memory_map is not None:
271
+ kwargs["memory_map"] = self.memory_map
272
+ if self.storage_options is not None:
273
+ kwargs["storage_options"] = self.storage_options
274
+ if self.row_count_name is not None:
275
+ kwargs["row_count_name"] = self.row_count_name
276
+ if self.row_count_offset is not None:
277
+ kwargs["row_count_offset"] = self.row_count_offset
278
+ if self.rechunk is not None:
279
+ kwargs["rechunk"] = self.rechunk
280
+ return kwargs
281
+
282
+ def load_data(self, type_: type) -> tuple[DATAFRAME_TYPE, dict[str, Any]]:
283
+ df = pl.scan_ipc(self.source, **self._get_loading_kwargs())
284
+ metadata = utils.get_file_metadata(self.source)
285
+ return df, metadata
286
+
287
+ @classmethod
288
+ def name(cls) -> str:
289
+ return "feather"
290
+
291
+
292
+ def register_data_loaders():
293
+ """Function to register the data loaders for this extension."""
294
+ for loader in [
295
+ PolarsScanCSVReader,
296
+ PolarsScanParquetReader,
297
+ PolarsScanFeatherReader,
298
+ ]:
299
+ registry.register_adapter(loader)
300
+
301
+
302
+ register_data_loaders()