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,98 @@
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
+ from typing import Any
19
+
20
+ from hamilton.data_quality import base, default_validators
21
+ from hamilton.htypes import custom_subclass_check
22
+
23
+ try:
24
+ import pydantic # noqa: F401
25
+ except ModuleNotFoundError as e:
26
+ raise NotImplementedError(
27
+ "Cannot import `pydantic` from `pydantic_validators`. Run pip install 'sf-hamilton[pydantic]' if needed."
28
+ ) from e
29
+
30
+ try:
31
+ from pydantic import BaseModel, TypeAdapter, ValidationError
32
+ except ImportError as e:
33
+ raise NotImplementedError(
34
+ "`pydantic>=2.0` required to use `pydantic_validators`. Run pip install 'sf-hamilton[pydantic]' if needed."
35
+ ) from e
36
+
37
+
38
+ COLUMN_FRIENDLY_DF_TYPE = False
39
+
40
+
41
+ class PydanticModelValidator(base.BaseDefaultValidator):
42
+ """Pydantic model compatibility validator (requires ``pydantic>=2.0``)
43
+
44
+ Note that this validator uses pydantic's strict mode, which does not allow for
45
+ coercion of data. This means that if an object does not exactly match the reference
46
+ type, it will fail validation, regardless of whether it could be coerced into the
47
+ correct type.
48
+
49
+ :param model: Pydantic model to validate against
50
+ :param importance: Importance of the validator, possible values "warn" and "fail"
51
+ :param arbitrary_types_allowed: Whether arbitrary types are allowed in the model
52
+ """
53
+
54
+ def __init__(self, model: type[BaseModel], importance: str):
55
+ super(PydanticModelValidator, self).__init__(importance)
56
+ self.model = model
57
+ self._model_adapter = TypeAdapter(model)
58
+
59
+ @classmethod
60
+ def applies_to(cls, datatype: type[type]) -> bool:
61
+ # In addition to checking for a subclass of BaseModel, we also check for dict
62
+ # as this is the standard 'de-serialized' format of pydantic models in python
63
+ return custom_subclass_check(datatype, BaseModel) or custom_subclass_check(datatype, dict)
64
+
65
+ def description(self) -> str:
66
+ return "Validates that the returned object is compatible with the specified pydantic model"
67
+
68
+ def validate(self, data: Any) -> base.ValidationResult:
69
+ try:
70
+ # Currently, validate can not alter the output data, so we must use
71
+ # strict=True. The downside to this is that data that could be coerced
72
+ # into the correct type will fail validation.
73
+ self._model_adapter.validate_python(data, strict=True)
74
+ except ValidationError as e:
75
+ return base.ValidationResult(
76
+ passes=False, message=str(e), diagnostics={"model_errors": e.errors()}
77
+ )
78
+ return base.ValidationResult(
79
+ passes=True,
80
+ message=f"Data passes pydantic check for model {str(self.model)}",
81
+ )
82
+
83
+ @classmethod
84
+ def arg(cls) -> str:
85
+ return "model"
86
+
87
+ @classmethod
88
+ def name(cls) -> str:
89
+ return "pydantic_validator"
90
+
91
+
92
+ def register_validators():
93
+ """Utility method to append pydantic validators as needed"""
94
+ validators = [PydanticModelValidator]
95
+ default_validators.AVAILABLE_DEFAULT_VALIDATORS.extend(validators)
96
+
97
+
98
+ register_validators()
@@ -0,0 +1,47 @@
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
+ from typing import Any
19
+
20
+ try:
21
+ import pyspark.pandas as ps
22
+ except ImportError as e:
23
+ raise NotImplementedError("Pyspark is not installed.") from e
24
+
25
+ from hamilton import registry
26
+
27
+ DATAFRAME_TYPE = ps.DataFrame
28
+ COLUMN_TYPE = ps.Series
29
+
30
+
31
+ @registry.get_column.register(ps.DataFrame)
32
+ def get_column_pyspark_pandas(df: ps.DataFrame, column_name: str) -> ps.Series:
33
+ return df[column_name]
34
+
35
+
36
+ @registry.fill_with_scalar.register(ps.DataFrame)
37
+ def fill_with_scalar_pyspark_pandas(df: ps.DataFrame, column_name: str, value: Any) -> ps.DataFrame:
38
+ df[column_name] = value
39
+ return df
40
+
41
+
42
+ def register_types():
43
+ """Function to register the types for this extension."""
44
+ registry.register_types("pyspark_pandas", DATAFRAME_TYPE, COLUMN_TYPE)
45
+
46
+
47
+ register_types()
@@ -0,0 +1,129 @@
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
20
+ from os import PathLike
21
+ from typing import Any, Union
22
+
23
+ try:
24
+ import sklearn.inspection
25
+ import sklearn.metrics
26
+ import sklearn.model_selection
27
+ from matplotlib import pyplot
28
+ except ImportError as e:
29
+ raise NotImplementedError("scikit-learn is not installed.") from e
30
+
31
+
32
+ from hamilton import registry
33
+ from hamilton.io import utils
34
+ from hamilton.io.data_adapters import DataSaver
35
+
36
+ display_classes = [
37
+ "ConfusionMatrixDisplay",
38
+ "DetCurveDisplay",
39
+ "PrecisionRecallDisplay",
40
+ "PredictionErrorDisplay",
41
+ "RocCurveDisplay",
42
+ "CalibrationDisplay",
43
+ "DecisionBoundaryDisplay",
44
+ "LearningCurveDisplay",
45
+ "PartialDependenceDisplay",
46
+ "ValidationCurveDisplay",
47
+ ]
48
+ SKLEARN_PLOT_TYPES = []
49
+ for class_name in display_classes:
50
+ # get the attribute via string from sklearn.metrics; if not found return None
51
+ class_metrics = getattr(sklearn.metrics, class_name, None)
52
+ class_inspection = getattr(sklearn.inspection, class_name, None)
53
+ class_model_selection = getattr(sklearn.model_selection, class_name, None)
54
+ if class_metrics:
55
+ SKLEARN_PLOT_TYPES.append(class_metrics)
56
+ if class_inspection:
57
+ SKLEARN_PLOT_TYPES.append(class_inspection)
58
+ if class_model_selection:
59
+ SKLEARN_PLOT_TYPES.append(class_model_selection)
60
+
61
+ SKLEARN_PLOT_TYPES.append(pyplot.Figure)
62
+ SKLEARN_PLOT_TYPES_ANNOTATION = Union[tuple(SKLEARN_PLOT_TYPES)]
63
+
64
+
65
+ @dataclasses.dataclass
66
+ class SklearnPlotSaver(DataSaver):
67
+ path: str | PathLike
68
+ # kwargs
69
+ dpi: float = 200
70
+ format: str = "png"
71
+ metadata: dict | None = None
72
+ bbox_inches: str = None
73
+ pad_inches: float = 0.1
74
+ backend: str | None = None
75
+ papertype: str = None
76
+ transparent: bool = None
77
+ bbox_extra_artists: list | None = None
78
+ pil_kwargs: dict | None = None
79
+
80
+ @classmethod
81
+ def applicable_types(cls) -> Collection[type]:
82
+ return SKLEARN_PLOT_TYPES
83
+
84
+ def _get_saving_kwargs(self) -> dict[str, Any]:
85
+ kwargs = {}
86
+ if self.dpi is not None:
87
+ kwargs["dpi"] = self.dpi
88
+ if self.format is not None:
89
+ kwargs["format"] = self.format
90
+ if self.metadata is not None:
91
+ kwargs["metadata"] = self.metadata
92
+ if self.bbox_inches is not None:
93
+ kwargs["bbox_inches"] = self.bbox_inches
94
+ if self.pad_inches is not None:
95
+ kwargs["pad_inches"] = self.pad_inches
96
+ if self.backend is not None:
97
+ kwargs["backend"] = self.backend
98
+ if self.papertype is not None:
99
+ kwargs["papertype"] = self.papertype
100
+ if self.transparent is not None:
101
+ kwargs["transparent"] = self.transparent
102
+ if self.bbox_extra_artists is not None:
103
+ kwargs["bbox_extra_artists"] = self.bbox_extra_artists
104
+ if self.pil_kwargs is not None:
105
+ kwargs["pil_kwargs"] = self.pil_kwargs
106
+ return kwargs
107
+
108
+ def save_data(self, data: SKLEARN_PLOT_TYPES_ANNOTATION) -> dict[str, Any]:
109
+ if isinstance(data, pyplot.Figure):
110
+ figure = data
111
+ else:
112
+ data.plot()
113
+ figure = data.figure_
114
+ figure.savefig(self.path, **self._get_saving_kwargs())
115
+ return utils.get_file_metadata(self.path)
116
+
117
+ @classmethod
118
+ def name(cls) -> str:
119
+ return "png"
120
+
121
+
122
+ def register_data_loaders():
123
+ """Function to register the data loaders for this extension."""
124
+ registry.register_adapter(SklearnPlotSaver)
125
+
126
+
127
+ register_data_loaders()
128
+
129
+ COLUMN_FRIENDLY_DF_TYPE = False
@@ -0,0 +1,105 @@
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 abc
19
+ import dataclasses
20
+ from collections.abc import Collection
21
+ from typing import Any
22
+
23
+ try:
24
+ import pyspark.sql as ps
25
+ except ImportError as e:
26
+ raise NotImplementedError("Pyspark is not installed.") from e
27
+
28
+ from pandas import DataFrame
29
+ from pyspark.sql import SparkSession
30
+
31
+ from hamilton import registry
32
+ from hamilton.io import utils
33
+ from hamilton.io.data_adapters import DataLoader
34
+
35
+
36
+ @dataclasses.dataclass
37
+ class SparkDataFrameDataLoader(DataLoader):
38
+ """Base class for data loaders that load pyspark dataframes.
39
+ We are not yet including data savers, but that will be added to this most likely..
40
+ """
41
+
42
+ spark: SparkSession
43
+
44
+ @classmethod
45
+ def applicable_types(cls) -> Collection[type]:
46
+ return [ps.DataFrame]
47
+
48
+ @abc.abstractmethod
49
+ def load_data(self, type_: type[DataFrame]) -> tuple[ps.DataFrame, dict[str, Any]]:
50
+ pass
51
+
52
+
53
+ @dataclasses.dataclass
54
+ class CSVDataLoader(SparkDataFrameDataLoader):
55
+ path: str # It supports multiple but for now we're going to have a single one
56
+ # We can always make that a list of strings, or make a multiple reader (.multicsv)
57
+ header: bool = True
58
+ sep: str = ","
59
+
60
+ def load_data(self, type_: type[DataFrame]) -> tuple[ps.DataFrame, dict[str, Any]]:
61
+ return (
62
+ self.spark.read.csv(self.path, header=self.header, sep=self.sep, inferSchema=True),
63
+ utils.get_file_metadata(self.path),
64
+ )
65
+
66
+ @classmethod
67
+ def name(cls) -> str:
68
+ return "csv"
69
+
70
+
71
+ @dataclasses.dataclass
72
+ class ParquetDataLoader(SparkDataFrameDataLoader):
73
+ path: str # It supports multiple but for now we're going to have a single one
74
+
75
+ # We can always make that a list of strings, or make a multiple reader (.multicsv)
76
+
77
+ def load_data(self, type_: type[DataFrame]) -> tuple[ps.DataFrame, dict[str, Any]]:
78
+ return self.spark.read.parquet(self.path), utils.get_file_metadata(self.path)
79
+
80
+ @classmethod
81
+ def name(cls) -> str:
82
+ return "parquet"
83
+
84
+
85
+ def register_data_loaders():
86
+ """Function to register the data loaders for this extension."""
87
+ for loader in [CSVDataLoader, ParquetDataLoader]:
88
+ registry.register_adapter(loader)
89
+
90
+
91
+ COLUMN_FRIENDLY_DF_TYPE = False
92
+
93
+ register_data_loaders()
94
+
95
+
96
+ DATAFRAME_TYPE = ps.DataFrame
97
+ COLUMN_TYPE = None
98
+
99
+
100
+ def register_types():
101
+ """Function to register the types for this extension."""
102
+ registry.register_types("spark", DATAFRAME_TYPE, COLUMN_TYPE)
103
+
104
+
105
+ register_types()
@@ -0,0 +1,51 @@
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
+ from typing import Any
19
+
20
+ import numpy as np
21
+
22
+ from hamilton import registry
23
+
24
+ try:
25
+ import vaex
26
+ except ImportError as e:
27
+ raise NotImplementedError("Vaex is not installed.") from e
28
+
29
+ DATAFRAME_TYPE = vaex.dataframe.DataFrame
30
+ COLUMN_TYPE = vaex.expression.Expression
31
+
32
+
33
+ @registry.get_column.register(vaex.dataframe.DataFrame)
34
+ def get_column_vaex(df: vaex.dataframe.DataFrame, column_name: str) -> vaex.expression.Expression:
35
+ return df[column_name]
36
+
37
+
38
+ @registry.fill_with_scalar.register(vaex.dataframe.DataFrame)
39
+ def fill_with_scalar_vaex(
40
+ df: vaex.dataframe.DataFrame, column_name: str, scalar_value: Any
41
+ ) -> vaex.dataframe.DataFrame:
42
+ df[column_name] = np.full((df.shape[0],), scalar_value)
43
+ return df
44
+
45
+
46
+ def register_types():
47
+ """Function to register the types for this extension."""
48
+ registry.register_types("vaex", DATAFRAME_TYPE, COLUMN_TYPE)
49
+
50
+
51
+ register_types()
@@ -0,0 +1,91 @@
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
20
+ from os import PathLike
21
+ from typing import Any, Union
22
+
23
+ try:
24
+ import xgboost
25
+ except ImportError as e:
26
+ raise NotImplementedError("XGBoost is not installed.") from e
27
+
28
+
29
+ from hamilton import registry
30
+ from hamilton.io import utils
31
+ from hamilton.io.data_adapters import DataLoader, DataSaver
32
+
33
+ XGBOOST_MODEL_TYPES = [xgboost.XGBModel, xgboost.Booster]
34
+ XGBOOST_MODEL_TYPES_ANNOTATION = Union[xgboost.XGBModel, xgboost.Booster]
35
+
36
+
37
+ @dataclasses.dataclass
38
+ class XGBoostJsonWriter(DataSaver):
39
+ """Write XGBoost models and boosters to json format
40
+ See differences with pickle format: https://xgboost.readthedocs.io/en/stable/tutorials/saving_model.html
41
+ """
42
+
43
+ path: str | PathLike
44
+
45
+ @classmethod
46
+ def applicable_types(cls) -> Collection[type]:
47
+ return XGBOOST_MODEL_TYPES
48
+
49
+ def save_data(self, data: XGBOOST_MODEL_TYPES_ANNOTATION) -> dict[str, Any]:
50
+ data.save_model(self.path)
51
+ return utils.get_file_metadata(self.path)
52
+
53
+ @classmethod
54
+ def name(cls) -> str:
55
+ return "json"
56
+
57
+
58
+ @dataclasses.dataclass
59
+ class XGBoostJsonReader(DataLoader):
60
+ """Load XGBoost models and boosters to json format
61
+ See differences with pickle format: https://xgboost.readthedocs.io/en/stable/tutorials/saving_model.html
62
+ """
63
+
64
+ path: str | bytearray | PathLike
65
+
66
+ @classmethod
67
+ def applicable_types(cls) -> Collection[type]:
68
+ return XGBOOST_MODEL_TYPES
69
+
70
+ def load_data(self, type_: type) -> tuple[XGBOOST_MODEL_TYPES_ANNOTATION, dict[str, Any]]:
71
+ model = type_()
72
+ model.load_model(self.path)
73
+ metadata = utils.get_file_metadata(self.path)
74
+ return model, metadata
75
+
76
+ @classmethod
77
+ def name(cls) -> str:
78
+ return "json"
79
+
80
+
81
+ def register_data_loaders():
82
+ for loader in [
83
+ XGBoostJsonReader,
84
+ XGBoostJsonWriter,
85
+ ]:
86
+ registry.register_adapter(loader)
87
+
88
+
89
+ register_data_loaders()
90
+
91
+ COLUMN_FRIENDLY_DF_TYPE = False
@@ -0,0 +1,89 @@
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
+ try:
19
+ import yaml
20
+ except ImportError as e:
21
+ raise NotImplementedError("yaml is not installed and is needed for yaml hamilton plugin") from e
22
+
23
+ import dataclasses
24
+ import pathlib
25
+ from collections.abc import Collection
26
+ from typing import Any, Union
27
+
28
+ from hamilton import registry
29
+ from hamilton.io.data_adapters import DataLoader, DataSaver
30
+ from hamilton.io.utils import get_file_metadata
31
+
32
+ PrimitiveTypes = str, int, float, bool, dict, list
33
+ AcceptedTypes = Union[PrimitiveTypes]
34
+
35
+
36
+ @dataclasses.dataclass
37
+ class YAMLDataLoader(DataLoader):
38
+ path: str | pathlib.Path
39
+
40
+ @classmethod
41
+ def applicable_types(cls) -> Collection[type]:
42
+ return [*PrimitiveTypes]
43
+
44
+ @classmethod
45
+ def name(cls) -> str:
46
+ return "yaml"
47
+
48
+ def load_data(self, type_: type) -> tuple[AcceptedTypes, dict[str, Any]]:
49
+ path = self.path
50
+ if isinstance(self.path, str):
51
+ path = pathlib.Path(self.path)
52
+
53
+ with path.open(mode="r") as f:
54
+ return yaml.safe_load(f), get_file_metadata(path)
55
+
56
+
57
+ @dataclasses.dataclass
58
+ class YAMLDataSaver(DataSaver):
59
+ path: str | pathlib.Path
60
+
61
+ @classmethod
62
+ def applicable_types(cls) -> Collection[type]:
63
+ return [*PrimitiveTypes]
64
+
65
+ @classmethod
66
+ def name(cls) -> str:
67
+ return "yaml"
68
+
69
+ def save_data(self, data: AcceptedTypes) -> dict[str, Any]:
70
+ path = self.path
71
+ if isinstance(path, str):
72
+ path = pathlib.Path(path)
73
+ with path.open("w") as f:
74
+ yaml.dump(data, f)
75
+ return get_file_metadata(self.path)
76
+
77
+
78
+ COLUMN_FRIENDLY_DF_TYPE = False
79
+
80
+
81
+ def register_data_loaders():
82
+ for materializer in [
83
+ YAMLDataLoader,
84
+ YAMLDataSaver,
85
+ ]:
86
+ registry.register_adapter(materializer)
87
+
88
+
89
+ register_data_loaders()