metaxy 0.0.1.dev3__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.
- metaxy/__init__.py +170 -0
- metaxy/_packaging.py +96 -0
- metaxy/_testing/__init__.py +55 -0
- metaxy/_testing/config.py +43 -0
- metaxy/_testing/metaxy_project.py +780 -0
- metaxy/_testing/models.py +111 -0
- metaxy/_testing/parametric/__init__.py +13 -0
- metaxy/_testing/parametric/metadata.py +664 -0
- metaxy/_testing/pytest_helpers.py +74 -0
- metaxy/_testing/runbook.py +533 -0
- metaxy/_utils.py +35 -0
- metaxy/_version.py +1 -0
- metaxy/cli/app.py +97 -0
- metaxy/cli/console.py +13 -0
- metaxy/cli/context.py +167 -0
- metaxy/cli/graph.py +610 -0
- metaxy/cli/graph_diff.py +290 -0
- metaxy/cli/list.py +46 -0
- metaxy/cli/metadata.py +317 -0
- metaxy/cli/migrations.py +999 -0
- metaxy/cli/utils.py +268 -0
- metaxy/config.py +680 -0
- metaxy/entrypoints.py +296 -0
- metaxy/ext/__init__.py +1 -0
- metaxy/ext/dagster/__init__.py +54 -0
- metaxy/ext/dagster/constants.py +10 -0
- metaxy/ext/dagster/dagster_type.py +156 -0
- metaxy/ext/dagster/io_manager.py +200 -0
- metaxy/ext/dagster/metaxify.py +512 -0
- metaxy/ext/dagster/observable.py +115 -0
- metaxy/ext/dagster/resources.py +27 -0
- metaxy/ext/dagster/selection.py +73 -0
- metaxy/ext/dagster/table_metadata.py +417 -0
- metaxy/ext/dagster/utils.py +462 -0
- metaxy/ext/sqlalchemy/__init__.py +23 -0
- metaxy/ext/sqlalchemy/config.py +29 -0
- metaxy/ext/sqlalchemy/plugin.py +353 -0
- metaxy/ext/sqlmodel/__init__.py +13 -0
- metaxy/ext/sqlmodel/config.py +29 -0
- metaxy/ext/sqlmodel/plugin.py +499 -0
- metaxy/graph/__init__.py +29 -0
- metaxy/graph/describe.py +325 -0
- metaxy/graph/diff/__init__.py +21 -0
- metaxy/graph/diff/diff_models.py +446 -0
- metaxy/graph/diff/differ.py +769 -0
- metaxy/graph/diff/models.py +443 -0
- metaxy/graph/diff/rendering/__init__.py +18 -0
- metaxy/graph/diff/rendering/base.py +323 -0
- metaxy/graph/diff/rendering/cards.py +188 -0
- metaxy/graph/diff/rendering/formatter.py +805 -0
- metaxy/graph/diff/rendering/graphviz.py +246 -0
- metaxy/graph/diff/rendering/mermaid.py +326 -0
- metaxy/graph/diff/rendering/rich.py +169 -0
- metaxy/graph/diff/rendering/theme.py +48 -0
- metaxy/graph/diff/traversal.py +247 -0
- metaxy/graph/status.py +329 -0
- metaxy/graph/utils.py +58 -0
- metaxy/metadata_store/__init__.py +32 -0
- metaxy/metadata_store/_ducklake_support.py +419 -0
- metaxy/metadata_store/base.py +1792 -0
- metaxy/metadata_store/bigquery.py +354 -0
- metaxy/metadata_store/clickhouse.py +184 -0
- metaxy/metadata_store/delta.py +371 -0
- metaxy/metadata_store/duckdb.py +446 -0
- metaxy/metadata_store/exceptions.py +61 -0
- metaxy/metadata_store/ibis.py +542 -0
- metaxy/metadata_store/lancedb.py +391 -0
- metaxy/metadata_store/memory.py +292 -0
- metaxy/metadata_store/system/__init__.py +57 -0
- metaxy/metadata_store/system/events.py +264 -0
- metaxy/metadata_store/system/keys.py +9 -0
- metaxy/metadata_store/system/models.py +129 -0
- metaxy/metadata_store/system/storage.py +957 -0
- metaxy/metadata_store/types.py +10 -0
- metaxy/metadata_store/utils.py +104 -0
- metaxy/metadata_store/warnings.py +36 -0
- metaxy/migrations/__init__.py +32 -0
- metaxy/migrations/detector.py +291 -0
- metaxy/migrations/executor.py +516 -0
- metaxy/migrations/generator.py +319 -0
- metaxy/migrations/loader.py +231 -0
- metaxy/migrations/models.py +528 -0
- metaxy/migrations/ops.py +447 -0
- metaxy/models/__init__.py +0 -0
- metaxy/models/bases.py +12 -0
- metaxy/models/constants.py +139 -0
- metaxy/models/feature.py +1335 -0
- metaxy/models/feature_spec.py +338 -0
- metaxy/models/field.py +263 -0
- metaxy/models/fields_mapping.py +307 -0
- metaxy/models/filter_expression.py +297 -0
- metaxy/models/lineage.py +285 -0
- metaxy/models/plan.py +232 -0
- metaxy/models/types.py +475 -0
- metaxy/py.typed +0 -0
- metaxy/utils/__init__.py +1 -0
- metaxy/utils/constants.py +2 -0
- metaxy/utils/exceptions.py +23 -0
- metaxy/utils/hashing.py +230 -0
- metaxy/versioning/__init__.py +31 -0
- metaxy/versioning/engine.py +656 -0
- metaxy/versioning/feature_dep_transformer.py +151 -0
- metaxy/versioning/ibis.py +249 -0
- metaxy/versioning/lineage_handler.py +205 -0
- metaxy/versioning/polars.py +189 -0
- metaxy/versioning/renamed_df.py +35 -0
- metaxy/versioning/types.py +63 -0
- metaxy-0.0.1.dev3.dist-info/METADATA +96 -0
- metaxy-0.0.1.dev3.dist-info/RECORD +111 -0
- metaxy-0.0.1.dev3.dist-info/WHEEL +4 -0
- metaxy-0.0.1.dev3.dist-info/entry_points.txt +4 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
"""Polars implementation of VersioningEngine."""
|
|
2
|
+
|
|
3
|
+
from collections.abc import Callable
|
|
4
|
+
from typing import cast
|
|
5
|
+
|
|
6
|
+
import narwhals as nw
|
|
7
|
+
import polars as pl
|
|
8
|
+
import polars_hash # noqa: F401 # Registers .nchash and .chash namespaces
|
|
9
|
+
from narwhals.typing import FrameT
|
|
10
|
+
|
|
11
|
+
from metaxy.versioning.engine import VersioningEngine
|
|
12
|
+
from metaxy.versioning.types import HashAlgorithm
|
|
13
|
+
|
|
14
|
+
# narwhals DataFrame backed by either a lazy or an eager frame
|
|
15
|
+
# PolarsFrame = TypeVar("PolarsFrame", pl.DataFrame, pl.LazyFrame)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class PolarsVersioningEngine(VersioningEngine):
|
|
19
|
+
"""Provenance engine using Polars and polars_hash plugin.
|
|
20
|
+
|
|
21
|
+
Only implements hash_string_column and build_struct_column.
|
|
22
|
+
All logic lives in the base class.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
# Map HashAlgorithm enum to polars-hash functions
|
|
26
|
+
_HASH_FUNCTION_MAP: dict[HashAlgorithm, Callable[[pl.Expr], pl.Expr]] = {
|
|
27
|
+
HashAlgorithm.XXHASH64: lambda expr: expr.nchash.xxhash64(), # pyright: ignore[reportAttributeAccessIssue]
|
|
28
|
+
HashAlgorithm.XXHASH32: lambda expr: expr.nchash.xxhash32(), # pyright: ignore[reportAttributeAccessIssue]
|
|
29
|
+
HashAlgorithm.WYHASH: lambda expr: expr.nchash.wyhash(), # pyright: ignore[reportAttributeAccessIssue]
|
|
30
|
+
HashAlgorithm.SHA256: lambda expr: expr.chash.sha2_256(), # pyright: ignore[reportAttributeAccessIssue]
|
|
31
|
+
HashAlgorithm.MD5: lambda expr: expr.nchash.md5(), # pyright: ignore[reportAttributeAccessIssue]
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@classmethod
|
|
35
|
+
def implementation(cls) -> nw.Implementation:
|
|
36
|
+
return nw.Implementation.POLARS
|
|
37
|
+
|
|
38
|
+
def hash_string_column(
|
|
39
|
+
self,
|
|
40
|
+
df: FrameT,
|
|
41
|
+
source_column: str,
|
|
42
|
+
target_column: str,
|
|
43
|
+
hash_algo: HashAlgorithm,
|
|
44
|
+
) -> FrameT:
|
|
45
|
+
"""Hash a string column using polars_hash.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
df: Narwhals DataFrame backed by Polars
|
|
49
|
+
source_column: Name of string column to hash
|
|
50
|
+
target_column: Name for the new column containing the hash
|
|
51
|
+
hash_algo: Hash algorithm to use
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
Narwhals DataFrame with new hashed column added, backed by Polars.
|
|
55
|
+
The source column remains unchanged.
|
|
56
|
+
"""
|
|
57
|
+
if hash_algo not in self._HASH_FUNCTION_MAP:
|
|
58
|
+
raise ValueError(
|
|
59
|
+
f"Hash algorithm {hash_algo} not supported. "
|
|
60
|
+
f"Supported: {list(self._HASH_FUNCTION_MAP.keys())}"
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
assert df.implementation == nw.Implementation.POLARS, (
|
|
64
|
+
"Only Polars DataFrames are accepted"
|
|
65
|
+
)
|
|
66
|
+
df_pl = cast(pl.DataFrame | pl.LazyFrame, df.to_native())
|
|
67
|
+
|
|
68
|
+
# Apply hash
|
|
69
|
+
hash_fn = self._HASH_FUNCTION_MAP[hash_algo]
|
|
70
|
+
hashed = hash_fn(polars_hash.col(source_column)).cast(pl.Utf8)
|
|
71
|
+
|
|
72
|
+
# Add new column with the hash
|
|
73
|
+
df_pl = df_pl.with_columns(hashed.alias(target_column))
|
|
74
|
+
|
|
75
|
+
# Convert back to Narwhals
|
|
76
|
+
return cast(FrameT, nw.from_native(df_pl))
|
|
77
|
+
|
|
78
|
+
@staticmethod
|
|
79
|
+
def build_struct_column(
|
|
80
|
+
df: FrameT,
|
|
81
|
+
struct_name: str,
|
|
82
|
+
field_columns: dict[str, str],
|
|
83
|
+
) -> FrameT:
|
|
84
|
+
"""Build a struct column from existing columns.
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
df: Narwhals DataFrame backed by Polars
|
|
88
|
+
struct_name: Name for the new struct column
|
|
89
|
+
field_columns: Mapping from struct field names to column names
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
Narwhals DataFrame with new struct column added, backed by Polars.
|
|
93
|
+
The source columns remain unchanged.
|
|
94
|
+
"""
|
|
95
|
+
assert df.implementation == nw.Implementation.POLARS, (
|
|
96
|
+
"Only Polars DataFrames are accepted"
|
|
97
|
+
)
|
|
98
|
+
df_pl = cast(pl.DataFrame | pl.LazyFrame, df.to_native())
|
|
99
|
+
|
|
100
|
+
# Build struct expression
|
|
101
|
+
struct_expr = pl.struct(
|
|
102
|
+
[
|
|
103
|
+
pl.col(col_name).alias(field_name)
|
|
104
|
+
for field_name, col_name in field_columns.items()
|
|
105
|
+
]
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
# Add struct column
|
|
109
|
+
df_pl = df_pl.with_columns(struct_expr.alias(struct_name))
|
|
110
|
+
|
|
111
|
+
# Convert back to Narwhals
|
|
112
|
+
return cast(FrameT, nw.from_native(df_pl))
|
|
113
|
+
|
|
114
|
+
@staticmethod
|
|
115
|
+
def aggregate_with_string_concat(
|
|
116
|
+
df: FrameT,
|
|
117
|
+
group_by_columns: list[str],
|
|
118
|
+
concat_column: str,
|
|
119
|
+
concat_separator: str,
|
|
120
|
+
exclude_columns: list[str],
|
|
121
|
+
) -> FrameT:
|
|
122
|
+
"""Aggregate DataFrame by grouping and concatenating strings.
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
df: Narwhals DataFrame backed by Polars
|
|
126
|
+
group_by_columns: Columns to group by
|
|
127
|
+
concat_column: Column containing strings to concatenate within groups
|
|
128
|
+
concat_separator: Separator to use when concatenating strings
|
|
129
|
+
exclude_columns: Columns to exclude from aggregation
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
Narwhals DataFrame with one row per group.
|
|
133
|
+
"""
|
|
134
|
+
assert df.implementation == nw.Implementation.POLARS, (
|
|
135
|
+
"Only Polars DataFrames are accepted"
|
|
136
|
+
)
|
|
137
|
+
df_pl = cast(pl.DataFrame | pl.LazyFrame, df.to_native())
|
|
138
|
+
|
|
139
|
+
# Group and aggregate: concatenate concat_column, take first for others
|
|
140
|
+
grouped = df_pl.group_by(group_by_columns).agg(
|
|
141
|
+
[
|
|
142
|
+
pl.col(concat_column).str.join(concat_separator),
|
|
143
|
+
pl.exclude(
|
|
144
|
+
group_by_columns + [concat_column] + exclude_columns
|
|
145
|
+
).first(),
|
|
146
|
+
]
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
# Convert back to Narwhals
|
|
150
|
+
return cast(FrameT, nw.from_native(grouped))
|
|
151
|
+
|
|
152
|
+
@staticmethod
|
|
153
|
+
def keep_latest_by_group(
|
|
154
|
+
df: FrameT,
|
|
155
|
+
group_columns: list[str],
|
|
156
|
+
timestamp_column: str,
|
|
157
|
+
) -> FrameT:
|
|
158
|
+
"""Keep only the latest row per group based on a timestamp column.
|
|
159
|
+
|
|
160
|
+
Args:
|
|
161
|
+
df: Narwhals DataFrame/LazyFrame backed by Polars
|
|
162
|
+
group_columns: Columns to group by (typically ID columns)
|
|
163
|
+
timestamp_column: Column to use for determining "latest" (typically metaxy_created_at)
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
Narwhals DataFrame/LazyFrame with only the latest row per group
|
|
167
|
+
|
|
168
|
+
Raises:
|
|
169
|
+
ValueError: If timestamp_column doesn't exist in df
|
|
170
|
+
"""
|
|
171
|
+
assert df.implementation == nw.Implementation.POLARS, (
|
|
172
|
+
"Only Polars DataFrames are accepted"
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
# Check if timestamp_column exists
|
|
176
|
+
if timestamp_column not in df.columns:
|
|
177
|
+
raise ValueError(
|
|
178
|
+
f"Timestamp column '{timestamp_column}' not found in DataFrame. "
|
|
179
|
+
f"Available columns: {df.columns}"
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
df_pl = cast(pl.DataFrame | pl.LazyFrame, df.to_native())
|
|
183
|
+
|
|
184
|
+
result = df_pl.group_by(group_columns).agg(
|
|
185
|
+
pl.col("*").sort_by(timestamp_column).last()
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
# Convert back to Narwhals
|
|
189
|
+
return cast(FrameT, nw.from_native(result))
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from collections.abc import Mapping, Sequence
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from typing import Generic
|
|
4
|
+
|
|
5
|
+
import narwhals as nw
|
|
6
|
+
from narwhals.typing import FrameT
|
|
7
|
+
from typing_extensions import Self
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass
|
|
11
|
+
class RenamedDataFrame(Generic[FrameT]):
|
|
12
|
+
"""A class representing a dataframe with renamed columns.
|
|
13
|
+
|
|
14
|
+
We keep ID columns together with this DataFrame to join on them later on."""
|
|
15
|
+
|
|
16
|
+
df: FrameT
|
|
17
|
+
id_columns: list[str]
|
|
18
|
+
|
|
19
|
+
def rename(self, mapping: Mapping[str, str]) -> Self:
|
|
20
|
+
if mapping:
|
|
21
|
+
# Convert Mapping to dict for narwhals rename
|
|
22
|
+
self.df = self.df.rename(dict(mapping))
|
|
23
|
+
self.id_columns = [mapping.get(col, col) for col in self.id_columns]
|
|
24
|
+
return self
|
|
25
|
+
|
|
26
|
+
def filter(self, filters: Sequence[nw.Expr] | None) -> Self:
|
|
27
|
+
if filters:
|
|
28
|
+
self.df = self.df.filter(*filters)
|
|
29
|
+
return self
|
|
30
|
+
|
|
31
|
+
def select(self, columns: Sequence[str] | None) -> Self:
|
|
32
|
+
if columns:
|
|
33
|
+
self.df = self.df.select(*columns)
|
|
34
|
+
self.id_columns = [col for col in self.id_columns if col in columns]
|
|
35
|
+
return self
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""Hash algorithms supported for field provenance calculation."""
|
|
2
|
+
|
|
3
|
+
from enum import Enum
|
|
4
|
+
from typing import Any, NamedTuple
|
|
5
|
+
|
|
6
|
+
import narwhals as nw
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class HashAlgorithm(Enum):
|
|
10
|
+
"""Supported hash algorithms for field provenance calculation.
|
|
11
|
+
|
|
12
|
+
These algorithms are chosen for:
|
|
13
|
+
- Speed (non-cryptographic hashes preferred)
|
|
14
|
+
- Cross-database availability
|
|
15
|
+
- Good collision resistance for field provenance calculation
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
XXHASH64 = "xxhash64" # Fast, available in DuckDB, ClickHouse, Polars
|
|
19
|
+
XXHASH32 = "xxhash32" # Faster for small data, less collision resistant
|
|
20
|
+
WYHASH = "wyhash" # Very fast, Polars-specific
|
|
21
|
+
SHA256 = "sha256" # Cryptographic, slower, universally available
|
|
22
|
+
MD5 = "md5" # Legacy, widely available, not recommended for new code
|
|
23
|
+
FARMHASH = "farmhash" # Better than MD5, available in BigQuery
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class Increment(NamedTuple):
|
|
27
|
+
"""Result of an incremental update containing eager dataframes.
|
|
28
|
+
|
|
29
|
+
Contains three sets of samples:
|
|
30
|
+
- added: New samples from upstream not present in current metadata
|
|
31
|
+
- changed: Samples with different provenance
|
|
32
|
+
- removed: Samples in current metadata but not in upstream state
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
added: nw.DataFrame[Any]
|
|
36
|
+
changed: nw.DataFrame[Any]
|
|
37
|
+
removed: nw.DataFrame[Any]
|
|
38
|
+
|
|
39
|
+
def collect(self) -> "Increment":
|
|
40
|
+
"""No-op for eager Increment (already collected)."""
|
|
41
|
+
return self
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class LazyIncrement(NamedTuple):
|
|
45
|
+
"""Result of an incremental update containing lazy dataframes.
|
|
46
|
+
|
|
47
|
+
Contains three sets of samples:
|
|
48
|
+
- added: New samples from upstream not present in current metadata
|
|
49
|
+
- changed: Samples with different provenance
|
|
50
|
+
- removed: Samples in current metadata but not in upstream state
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
added: nw.LazyFrame[Any]
|
|
54
|
+
changed: nw.LazyFrame[Any]
|
|
55
|
+
removed: nw.LazyFrame[Any]
|
|
56
|
+
|
|
57
|
+
def collect(self) -> Increment:
|
|
58
|
+
"""Collect all lazy frames to eager DataFrames."""
|
|
59
|
+
return Increment(
|
|
60
|
+
added=self.added.collect(),
|
|
61
|
+
changed=self.changed.collect(),
|
|
62
|
+
removed=self.removed.collect(),
|
|
63
|
+
)
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: metaxy
|
|
3
|
+
Version: 0.0.1.dev3
|
|
4
|
+
Summary: Pluggable versioned metadata management for incremental multi-modal pipelines.
|
|
5
|
+
Author: Daniel Gafni
|
|
6
|
+
Author-email: Daniel Gafni <danielgafni16@gmail.com>
|
|
7
|
+
Classifier: Development Status :: 2 - Pre-Alpha
|
|
8
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
+
Classifier: Typing :: Typed
|
|
15
|
+
Requires-Dist: cyclopts
|
|
16
|
+
Requires-Dist: narwhals>=2.9.0
|
|
17
|
+
Requires-Dist: platformdirs>=4.5.0
|
|
18
|
+
Requires-Dist: polars>=1.33.1
|
|
19
|
+
Requires-Dist: polars-hash>=0.5.1
|
|
20
|
+
Requires-Dist: pydantic>=2.11.9
|
|
21
|
+
Requires-Dist: pydantic-settings>=2.11.0
|
|
22
|
+
Requires-Dist: pyyaml>=6.0.0
|
|
23
|
+
Requires-Dist: sqlglot>=27.29.0
|
|
24
|
+
Requires-Dist: tomli>=2.3.0
|
|
25
|
+
Requires-Dist: rich>=13.0.0
|
|
26
|
+
Requires-Dist: ibis-framework[bigquery]>=11.0.0 ; extra == 'bigquery'
|
|
27
|
+
Requires-Dist: ibis-framework[clickhouse]>=11.0.0 ; extra == 'clickhouse'
|
|
28
|
+
Requires-Dist: dagster>=1.12.3 ; extra == 'dagster'
|
|
29
|
+
Requires-Dist: deltalake>=1.2.1 ; extra == 'delta'
|
|
30
|
+
Requires-Dist: ibis-framework[duckdb]>=11.0.0 ; extra == 'duckdb'
|
|
31
|
+
Requires-Dist: duckdb>=1.4.1 ; extra == 'duckdb'
|
|
32
|
+
Requires-Dist: pygraphviz>=1.14 ; extra == 'graphviz'
|
|
33
|
+
Requires-Dist: pyarrow>=18.0.0 ; extra == 'ibis'
|
|
34
|
+
Requires-Dist: ibis-framework>=11.0.0 ; extra == 'ibis'
|
|
35
|
+
Requires-Dist: lancedb>=0.15.0 ; extra == 'lancedb'
|
|
36
|
+
Requires-Dist: mermaid-py>=0.8.0 ; extra == 'mermaid'
|
|
37
|
+
Requires-Dist: sqlmodel>=0.0.27 ; extra == 'sqlmodel'
|
|
38
|
+
Requires-Python: >=3.10
|
|
39
|
+
Project-URL: Documentation, https://metaxy.dev
|
|
40
|
+
Project-URL: Issues, https://github.com/anam-org/metaxy/issues
|
|
41
|
+
Project-URL: Repository, https://github.com/anam-org/metaxy
|
|
42
|
+
Provides-Extra: bigquery
|
|
43
|
+
Provides-Extra: clickhouse
|
|
44
|
+
Provides-Extra: dagster
|
|
45
|
+
Provides-Extra: delta
|
|
46
|
+
Provides-Extra: duckdb
|
|
47
|
+
Provides-Extra: graphviz
|
|
48
|
+
Provides-Extra: ibis
|
|
49
|
+
Provides-Extra: lancedb
|
|
50
|
+
Provides-Extra: mermaid
|
|
51
|
+
Provides-Extra: sqlmodel
|
|
52
|
+
Description-Content-Type: text/markdown
|
|
53
|
+
|
|
54
|
+
<p align="center">
|
|
55
|
+
<img src="https://raw.githubusercontent.com/anam-org/metaxy/main/docs/assets/metaxy.svg" alt="Metaxy Logo" width="100"/>
|
|
56
|
+
</p>
|
|
57
|
+
|
|
58
|
+
<h1 align="center">Metaxy</h1>
|
|
59
|
+
|
|
60
|
+
<p align="center">
|
|
61
|
+
<a href="https://pypi.org/project/metaxy/"><img src="https://img.shields.io/pypi/v/metaxy.svg?color=4644ad" alt="PyPI version"></a>
|
|
62
|
+
<a href="https://pypi.org/project/metaxy/"><img src="https://img.shields.io/pypi/pyversions/metaxy.svg?color=4644ad" alt="Python versions"></a>
|
|
63
|
+
<a href="https://pypi.org/project/metaxy/"><img src="https://img.shields.io/pypi/dm/metaxy.svg?color=4644ad" alt="PyPI downloads"></a>
|
|
64
|
+
<a href="https://github.com/anam-org/metaxy/actions/workflows/QA.yml"><img src="https://github.com/anam-org/metaxy/actions/workflows/QA.yml/badge.svg" alt="CI"></a>
|
|
65
|
+
<a href="https://docs.astral.sh/ruff/"><img src="https://img.shields.io/badge/linting-ruff-4644ad" alt="Ruff"></a>
|
|
66
|
+
<a href="https://docs.basedpyright.com"><img src="https://img.shields.io/badge/basedpyright-checked-4644ad" alt="basedpyright - checked"></a>
|
|
67
|
+
<a href="https://prek.j178.dev"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/j178/prek/master/assets/badge/v0.json" alt="prek"></a>
|
|
68
|
+
</p>
|
|
69
|
+
|
|
70
|
+
Metaxy is a metadata layer for **multi-modal Data and ML pipelines**. Metaxy tracks feature versions, (partial) data dependencies, and lineage across complex computation graphs.
|
|
71
|
+
|
|
72
|
+
Metaxy's goal is to provide a standard instrument for any kind of multi-modal (or just tabular) **incremental** pipelines, standardizing dependency specification, versioning, partial data dependencies, manipulations over metadata, migrations, and more.
|
|
73
|
+
|
|
74
|
+
Read the [docs](https://anam-org.github.io/metaxy) to learn more.
|
|
75
|
+
|
|
76
|
+
## Installation
|
|
77
|
+
|
|
78
|
+
**Warning**: Metaxy hasn't been publicly released yet, but you can try the latest dev release:
|
|
79
|
+
|
|
80
|
+
```shell
|
|
81
|
+
pip install --pre metaxy
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Integrating Metaxy in your project
|
|
85
|
+
|
|
86
|
+
Metaxy is highly pluggable and generally can be used with any kind of incremental pipelines, storage, metadata stores, and dataframe libraries.
|
|
87
|
+
|
|
88
|
+
Metaxy provides integrations with popular tools such as [Dagster](https://anam-org.github.io/metaxy/main/integrations/orchestration/dagster), [ClickHouse](https://anam-org.github.io/metaxy/main/integrations/metadata-stores/databases/clickhouse), [DeltaLake](https://anam-org.github.io/metaxy/main/integrations/metadata-stores/storage/delta/), [SQLModel](https://anam-org.github.io/metaxy/main/integrations/plugins/sqlmodel/).
|
|
89
|
+
|
|
90
|
+
The full list can be found [here](https://anam-org.github.io/metaxy/main/integrations).
|
|
91
|
+
|
|
92
|
+
## Contributing
|
|
93
|
+
|
|
94
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
95
|
+
|
|
96
|
+
<img referrerpolicy="no-referrer" src="https://static.scarf.sh/a.png?x-pxid=22cb75dc-201e-4a72-9fb2-c3a53ce9207e&page=README.md" />
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
metaxy/__init__.py,sha256=iqk7EB_rbosaNkJKDglZpHcrSISBc7DgrRMjr4Jr0W0,4373
|
|
2
|
+
metaxy/_packaging.py,sha256=E4r8UpfaBirWJcBy23FFNjTvwR76TUXHTY5M-XT-l58,3456
|
|
3
|
+
metaxy/_testing/__init__.py,sha256=YdvmjhYrdrUFEf5XhXAlPe6F3xHxEBojroIpgPBkjM4,1446
|
|
4
|
+
metaxy/_testing/config.py,sha256=PWLHCNxZoeVjAs57U2_XqaXalQSdetZO0I2fpeheyoY,1147
|
|
5
|
+
metaxy/_testing/metaxy_project.py,sha256=A1tENVruFFYtHWJb1nUfc18i_vPzt2JTZgegMSns1Uk,27070
|
|
6
|
+
metaxy/_testing/models.py,sha256=f6VFHWe5rYIxFwLOfwLoJiRawLuYIU3g5FU1b3X7_2Q,3501
|
|
7
|
+
metaxy/_testing/parametric/__init__.py,sha256=0nsF2OnNBazpRKVdjYVxaydpg3r-Ikwv5zaERnQv7IQ,347
|
|
8
|
+
metaxy/_testing/parametric/metadata.py,sha256=ll7VKAOaZ8cDPSf1mnAJNLUCol5_qJfT57UipTGubUw,25305
|
|
9
|
+
metaxy/_testing/pytest_helpers.py,sha256=0sTLLt27SSSNNr8SpbOUbmQdgUuZ-3fc3Qf0pchVFts,2304
|
|
10
|
+
metaxy/_testing/runbook.py,sha256=iYlx_SMOJwBoYwcdWn-covS0JwsIBfn7WhNo7TspMk4,17020
|
|
11
|
+
metaxy/_utils.py,sha256=PuuCmbn0Ig9VQ8g3Xn4WM1YGs5gSlehdMcxLNqg-To4,963
|
|
12
|
+
metaxy/_version.py,sha256=Nen3Jr4Cj-VxPTIW8M9gKf9vB4abvgirtm4TCaKcqck,27
|
|
13
|
+
metaxy/cli/app.py,sha256=mO2j3Yj7tpLE83pV9tRAbEhBrZCtXPzA_wYY5BJ1W0o,3081
|
|
14
|
+
metaxy/cli/console.py,sha256=3aOSOcK1YLrox1U8azNDIN0W7rRETeFd84UYXczIOX0,464
|
|
15
|
+
metaxy/cli/context.py,sha256=KphESWzHEoDGr26xnLee-VPk9Ruu3YK_jw4173GpLkg,5174
|
|
16
|
+
metaxy/cli/graph.py,sha256=hSpcV6fXzULqdHN0am52NHtTgeAlLIfrF08OfIDC8fo,22437
|
|
17
|
+
metaxy/cli/graph_diff.py,sha256=kloqqBcfdRdkeY1DoxLU-WxxLgZ0cw4EDTMZR3PgfCA,10067
|
|
18
|
+
metaxy/cli/list.py,sha256=4Sf-B9XRaeyuZa7zeUGHMRPpVocDyGr1xZc6eLG3Rcw,1625
|
|
19
|
+
metaxy/cli/metadata.py,sha256=2LH3474dcz8r1Ns8rpD3H9X9R6Fk3e4AnWrgxyPDdeI,10276
|
|
20
|
+
metaxy/cli/migrations.py,sha256=JL-T7l_DsCLX101_vtEyNMOZQfpqHw7Fzamp0GHYtU0,38519
|
|
21
|
+
metaxy/cli/utils.py,sha256=GNcZOgd0DxBXC5wFC-YQwBrgnSRytRPCXpqhNFiG9I0,8762
|
|
22
|
+
metaxy/config.py,sha256=akx_47aV56NMFBdzlc4t8LBikMQYfaECDE1HPIIZbj8,23651
|
|
23
|
+
metaxy/entrypoints.py,sha256=mJQeaBCN4OhEYxgICZc_4DgdQCPTH95y1x1SQ40Wmp0,9174
|
|
24
|
+
metaxy/ext/__init__.py,sha256=Y0-7EQCcv9XhoJCjAJtSYd74r49qbsken2VPQBxXs5c,46
|
|
25
|
+
metaxy/ext/dagster/__init__.py,sha256=APkjOqQIsvAULhi1R9qZVeh3SFjdGasShlO87AWYnH0,1737
|
|
26
|
+
metaxy/ext/dagster/constants.py,sha256=U0UhaPGjJu7p-iRuhB2oi1sSgtMf0HXAhiwfwAJYpLk,408
|
|
27
|
+
metaxy/ext/dagster/dagster_type.py,sha256=mhJoNmDrWN7ITshWtAm2ZaUf38WGZzLAJlQbK3kb4F4,5633
|
|
28
|
+
metaxy/ext/dagster/io_manager.py,sha256=_6m-k25SmA7WuloUDEL0JhAappIjSPlWyPYD_AyWo7o,7754
|
|
29
|
+
metaxy/ext/dagster/metaxify.py,sha256=-q4T3mFoxt5s3I8_TKCD1BYa8UNbOOkup_qiw0T3g08,20700
|
|
30
|
+
metaxy/ext/dagster/observable.py,sha256=AOAnP6MXijYIekZUqak4JXecHsfj5Pfw1m0HBQ7aA4Q,4588
|
|
31
|
+
metaxy/ext/dagster/resources.py,sha256=zvsZSiNypAb4NBE4TnNZYwOXLLMswVMivs4DTmYwYwE,973
|
|
32
|
+
metaxy/ext/dagster/selection.py,sha256=LNWQGrGhddeaLI_Ae1N9nL5DKqttNlJAk5JNHsKq_aE,2319
|
|
33
|
+
metaxy/ext/dagster/table_metadata.py,sha256=2eIIw5r2iIeAHPuUzVkz_dncb64zHurH02APj6JjjYg,16349
|
|
34
|
+
metaxy/ext/dagster/utils.py,sha256=U6rvltA9qKvQkd4U2eok4sRBoYamUf7NJITmFL5Ippw,16945
|
|
35
|
+
metaxy/ext/sqlalchemy/__init__.py,sha256=PhFD-eq-eqlZr6zsgOukG0vJIWFz6U1qRWlP4htNN60,710
|
|
36
|
+
metaxy/ext/sqlalchemy/config.py,sha256=wrx8zGCEECT5knwnqKxFMbXoar2jwvIGK1HYMZWaNk0,1001
|
|
37
|
+
metaxy/ext/sqlalchemy/plugin.py,sha256=7DmqOl-xX8jdvoX7DGwoRa4NOK8RG-q9JH4wKXNiqVA,11597
|
|
38
|
+
metaxy/ext/sqlmodel/__init__.py,sha256=HHkIfSHctr0DGYVkqPHtWniPtV-vdy2eB7r-V6jQUtA,328
|
|
39
|
+
metaxy/ext/sqlmodel/config.py,sha256=stPet5NeP_PropJ5GA00fdZLHPbBzV_c-ldM9FgqiXc,1003
|
|
40
|
+
metaxy/ext/sqlmodel/plugin.py,sha256=9ibu29ZiPGJmB8mTyLjTFgHKPYMZe_A6Rl3PTPpADbQ,18717
|
|
41
|
+
metaxy/graph/__init__.py,sha256=oK7P_GSkTp-FlbulbvTTYc-MD9p2rxFCewIDVMcifJc,620
|
|
42
|
+
metaxy/graph/describe.py,sha256=C02MAVz0WO0PBeMDQ_CFQUNFc9bVnFpMZVRyEp74hnU,10598
|
|
43
|
+
metaxy/graph/diff/__init__.py,sha256=sP467NBNZnL3IRUA-uqKjXkJiOJPHrxvr5sMosS7PTQ,399
|
|
44
|
+
metaxy/graph/diff/diff_models.py,sha256=fFEixXa0KHWeStaJ2699IOMbSbeBJagz_aSsge4vQ9o,16928
|
|
45
|
+
metaxy/graph/diff/differ.py,sha256=J9Ur2tryqMHW0AdlsQFd2YB4Yc3a6RggqBqEJgrBnrc,29894
|
|
46
|
+
metaxy/graph/diff/models.py,sha256=w-HkJqWgYsXNP1B6amGzdOp5eAztftXVIq0Wr5JW8gM,16027
|
|
47
|
+
metaxy/graph/diff/rendering/__init__.py,sha256=gRJXWnzF3KEs4vwgOk9XXxvsOXIkaVgicYLtSOKfC5A,606
|
|
48
|
+
metaxy/graph/diff/rendering/base.py,sha256=IlFxl17lm45zTzFB26_CK7KNlfzaJ23ti7XCtCkgGeI,10267
|
|
49
|
+
metaxy/graph/diff/rendering/cards.py,sha256=nGBJ6s5vSMyKgFbuz2CKdLZu-FidLXB8U8NLEe32oqw,6507
|
|
50
|
+
metaxy/graph/diff/rendering/formatter.py,sha256=swDrBg0vRuBKxmoiyfhpytEEietolwOqc78EUoH7DFY,32337
|
|
51
|
+
metaxy/graph/diff/rendering/graphviz.py,sha256=OEhar2AFdAM6DcYe-aamMRyCJ8sRbLE6VNA4vNc44rw,7946
|
|
52
|
+
metaxy/graph/diff/rendering/mermaid.py,sha256=V-ggXGzhfTADwPIsaOodXp0dTNEPpJ-poFQGxLdjL_4,11195
|
|
53
|
+
metaxy/graph/diff/rendering/rich.py,sha256=Hub0G6eMB_Qa4HUaken8TfEC8FMEKjaWWOHsnXiElnA,6133
|
|
54
|
+
metaxy/graph/diff/rendering/theme.py,sha256=z0hXs7a9TYjjUO2eyibL6RknxQU0RFA5_962AG7a2qs,1689
|
|
55
|
+
metaxy/graph/diff/traversal.py,sha256=KsuKr6lDw7h7S7qVlMWF0nwjAkjWErP4kyVub9AIlaI,8146
|
|
56
|
+
metaxy/graph/status.py,sha256=gNWLUDMa_UlfmWWTYGqRKyjLoUM-6prXKLOhppZQu7Y,11508
|
|
57
|
+
metaxy/graph/utils.py,sha256=E5FHHyTCn0o1o8gfmBEu2ntHv3nlkIoMCDet_MdLJoI,1311
|
|
58
|
+
metaxy/metadata_store/__init__.py,sha256=p83tu5RYCvjp5EicOyUqY1owKNEYgwi7rJOucmijVx8,895
|
|
59
|
+
metaxy/metadata_store/_ducklake_support.py,sha256=eP-i4m6G24bE77r184nMXF1ip5ZRhKJ3VKEXJ2A90j8,15147
|
|
60
|
+
metaxy/metadata_store/base.py,sha256=zfWuhWP260ZgJIiJ6dtdgPbqSj3gB2Bz-E6fWEX6MYs,72430
|
|
61
|
+
metaxy/metadata_store/bigquery.py,sha256=5NEoquZYQ4DuGYjJGDBAqfelirZkdWuf0pHav4Pev1E,13303
|
|
62
|
+
metaxy/metadata_store/clickhouse.py,sha256=oYKocRZ6K3tJywv1FSJ6lt2hBiTGX96yqMXWRmXpKZE,6074
|
|
63
|
+
metaxy/metadata_store/delta.py,sha256=CwnbvGghYlzF5HHvLrJ7MM_l7hHrm7HUSuU8P2EB4T4,13837
|
|
64
|
+
metaxy/metadata_store/duckdb.py,sha256=rXC3Hcd9QFtqQt2phvt1ygaH_U-haC3rB-GuX8nE0u8,16299
|
|
65
|
+
metaxy/metadata_store/exceptions.py,sha256=3fask4dmaKIDr0WSV-Rx6eFioN7YLfDXrJXv2LBExAs,1340
|
|
66
|
+
metaxy/metadata_store/ibis.py,sha256=9ZLHmW3YJg5NnJFzHR0znz3n_SXF6Rszr3mltponuOg,19553
|
|
67
|
+
metaxy/metadata_store/lancedb.py,sha256=WyEUoGO-rEL3eL_ld3B-gHRCCYToo9gkIZGyrUs3o5s,13988
|
|
68
|
+
metaxy/metadata_store/memory.py,sha256=x79IR9Uhtl06BwIpgtZyIXHOXbPhtgrtRvlIbpBVHgA,10099
|
|
69
|
+
metaxy/metadata_store/system/__init__.py,sha256=b1K5jJkqMrbfN_P6aQbAYfr_Yyv1dHGqTeIrg3EzNls,1292
|
|
70
|
+
metaxy/metadata_store/system/events.py,sha256=oJa_mE6rNRO7P6McMSjkCUAKfdLgxYomOAAJaCh9qYs,8112
|
|
71
|
+
metaxy/metadata_store/system/keys.py,sha256=x8qNVQe4xqVMCHDr3bgrv3iRkI2IfFWxt0Qs1EEh7i4,292
|
|
72
|
+
metaxy/metadata_store/system/models.py,sha256=XZ-DRgiOTFm1N3qKUWpX5Isubi0cn8JeZvBfq617l-A,4494
|
|
73
|
+
metaxy/metadata_store/system/storage.py,sha256=bmwCORadefASy90kv5lG7fXEs6Etd8-AFq5-vxCQVRs,36093
|
|
74
|
+
metaxy/metadata_store/types.py,sha256=tEBOmYsA5oTdgkfmkRXfNQGdxwqXwDW-tG28cMKJ42Q,400
|
|
75
|
+
metaxy/metadata_store/utils.py,sha256=8ktzGG4LxMC0jngymakoHUAQbSKoseldJGaNCajWq-Y,3417
|
|
76
|
+
metaxy/metadata_store/warnings.py,sha256=wj0LKniSlSD1GHDqfUQ8nhlgD_omizgvLnSycNlrOwg,1021
|
|
77
|
+
metaxy/migrations/__init__.py,sha256=1_ZmPq0tweVYGRqaF1qif6zNjqfgGW0Ol5h8zOMs73w,815
|
|
78
|
+
metaxy/migrations/detector.py,sha256=tXIBM71wA5sU22l00vDbnagxZ9b8LvF1920EeesRJdU,10523
|
|
79
|
+
metaxy/migrations/executor.py,sha256=EZTuRdJqAOgLrDMO9maqWI_mUhr5bgsgDUpwqiS-rW0,19748
|
|
80
|
+
metaxy/migrations/generator.py,sha256=wIkW5jYQqYj-X-EjF12RRT5PpVQrHj28vPsUAQFV3Vc,12036
|
|
81
|
+
metaxy/migrations/loader.py,sha256=b56ZN68k-X8el6Ta2lKE_LKbCmdsWxI6Rxy6KrDZvX4,7317
|
|
82
|
+
metaxy/migrations/models.py,sha256=vROWErYBoTPy-c8hVlkI_2ujdTmYDBOwuI3pg2RanYc,18396
|
|
83
|
+
metaxy/migrations/ops.py,sha256=1DPn0DhEsxusNdHhEdLtHkS8GP8Mcbd7YiKSy0jgMJg,17275
|
|
84
|
+
metaxy/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
85
|
+
metaxy/models/bases.py,sha256=RbbJnOZKhvCe3qXOth2b5saeazkbcBLr0DVpdXytPuc,303
|
|
86
|
+
metaxy/models/constants.py,sha256=0V9sdtGPhywHE12tLzCIsXHCWIUn0PAU_v7TBLeEUNI,4852
|
|
87
|
+
metaxy/models/feature.py,sha256=qv4-DNuXNee0S1Qil3MgQIBSDZt4KE3BftGurfyiw1c,51965
|
|
88
|
+
metaxy/models/feature_spec.py,sha256=5OVTZ2cZmRuZQdch-t0hnnoiz90m3NHWtv3NAXZw6G0,12820
|
|
89
|
+
metaxy/models/field.py,sha256=H1E5QNZdz3_diEYTSutIzE3YNZOBL-UChywYyq0QmYA,8344
|
|
90
|
+
metaxy/models/fields_mapping.py,sha256=89zyyCE6LtPxbXIJJOHEVPXqt6ztJzEVl2YUnvK37oQ,10056
|
|
91
|
+
metaxy/models/filter_expression.py,sha256=Eid2-7W8x5ETYdj5ri6xY69dVPRXqUKFIylTqns9PbA,9599
|
|
92
|
+
metaxy/models/lineage.py,sha256=YddbUrr1ELkN-_9Sin1nMq-a5MEc5FcI5HUyr7l-LuY,10051
|
|
93
|
+
metaxy/models/plan.py,sha256=sO7k7rLWxZc_X2jJxhRZkHvIkrpFCvYZUuY8ebIb6AE,8420
|
|
94
|
+
metaxy/models/types.py,sha256=USlHQXdYkSMzlEifw0s98l6e3ug7WTnyuCXcL4md-P0,14839
|
|
95
|
+
metaxy/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
96
|
+
metaxy/utils/__init__.py,sha256=d2KPC4jX4iGQX7uQMfQHMfrRNz9MqywiuVY8prjNVhE,34
|
|
97
|
+
metaxy/utils/constants.py,sha256=1LyZxlVpxuU8BF4i3RO-GXehqcE_8WACruOX79vb1rE,100
|
|
98
|
+
metaxy/utils/exceptions.py,sha256=3l0IlF1KvYRuw6EgDjZLurSsvJqq0AURLil4xpA6h2s,687
|
|
99
|
+
metaxy/utils/hashing.py,sha256=4V_CkIJbAs0RKD6z1N-p1nnqsDgdOHHNOjXiL-uOTac,6580
|
|
100
|
+
metaxy/versioning/__init__.py,sha256=Ae_dQhPyJwLBY_IiDzdEGhAoAzYKBzCSnPA_ZlrttzU,1088
|
|
101
|
+
metaxy/versioning/engine.py,sha256=kTIWRSpn4eDdX6y2i-yleXxK_sY1dx2z-VU9NlAdiAw,26911
|
|
102
|
+
metaxy/versioning/feature_dep_transformer.py,sha256=7dbznclFIXQNCNlBRaidvHUaIBavxanf2WR66JpQKTg,5327
|
|
103
|
+
metaxy/versioning/ibis.py,sha256=e6HdRJ5sgfoTziRmrCo62O_h2GRkPuQ6jCkl4RXdY-E,8614
|
|
104
|
+
metaxy/versioning/lineage_handler.py,sha256=0wAYT43jXBWzUJb1jhRAsRXNc3BZYcA5A7CQlAu9uAE,7397
|
|
105
|
+
metaxy/versioning/polars.py,sha256=WcpeG1kyawZ3m1f-kqmghoVRddt-fhQCRnwmaKsnNlA,6761
|
|
106
|
+
metaxy/versioning/renamed_df.py,sha256=D3ALHJ4uUIaGrK3TlsH85SvUY8URQlaozyT4_zBU-80,1109
|
|
107
|
+
metaxy/versioning/types.py,sha256=--Zejj26-qFNA6BMwUn29SWTSCVmNMxy1JGxczU7IwE,2087
|
|
108
|
+
metaxy-0.0.1.dev3.dist-info/WHEEL,sha256=pFCy50wRV2h7SjJ35YOsQUupaV45rMdgpNIvnXbG5bE,79
|
|
109
|
+
metaxy-0.0.1.dev3.dist-info/entry_points.txt,sha256=HbLOdNbhhIxa_TzEsN3QRWki5LuctCJR_xkC7JoYsN4,73
|
|
110
|
+
metaxy-0.0.1.dev3.dist-info/METADATA,sha256=5xwZ65WWLPE7__N2BP0-8HMPd7M6FJsSCRTPf5HTRZc,4869
|
|
111
|
+
metaxy-0.0.1.dev3.dist-info/RECORD,,
|