datachain 0.3.4__py3-none-any.whl → 0.3.5__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.

Potentially problematic release.


This version of datachain might be problematic. Click here for more details.

@@ -1,34 +1,6 @@
1
- from datetime import datetime
2
-
3
1
  from pydantic import BaseModel
4
2
 
5
3
  from datachain.lib.model_store import ModelStore
6
- from datachain.sql.types import (
7
- JSON,
8
- Array,
9
- Binary,
10
- Boolean,
11
- DateTime,
12
- Float,
13
- Int,
14
- Int32,
15
- Int64,
16
- NullType,
17
- String,
18
- )
19
-
20
- DATACHAIN_TO_TYPE = {
21
- Int: int,
22
- Int32: int,
23
- Int64: int,
24
- String: str,
25
- Float: float,
26
- Boolean: bool,
27
- DateTime: datetime,
28
- Binary: bytes,
29
- Array(NullType): list,
30
- JSON: dict,
31
- }
32
4
 
33
5
 
34
6
  def flatten(obj: BaseModel):
datachain/lib/dc.py CHANGED
@@ -1224,14 +1224,11 @@ class DataChain(DatasetQuery):
1224
1224
  """
1225
1225
  headers, max_length = self._effective_signals_schema.get_headers_with_length()
1226
1226
  if flatten or max_length < 2:
1227
- columns = []
1228
- if headers:
1229
- columns = [".".join(filter(None, header)) for header in headers]
1230
- return pd.DataFrame.from_records(self.to_records(), columns=columns)
1227
+ columns = [".".join(filter(None, header)) for header in headers]
1228
+ else:
1229
+ columns = pd.MultiIndex.from_tuples(map(tuple, headers))
1231
1230
 
1232
- return pd.DataFrame(
1233
- self.results(), columns=pd.MultiIndex.from_tuples(map(tuple, headers))
1234
- )
1231
+ return pd.DataFrame.from_records(self.results(), columns=columns)
1235
1232
 
1236
1233
  def show(
1237
1234
  self,
@@ -1524,6 +1521,7 @@ class DataChain(DatasetQuery):
1524
1521
  to_insert: Optional[Union[dict, list[dict]]],
1525
1522
  session: Optional[Session] = None,
1526
1523
  in_memory: bool = False,
1524
+ schema: Optional[dict[str, DataType]] = None,
1527
1525
  ) -> "DataChain":
1528
1526
  """Create a DataChain from the provided records. This method can be used for
1529
1527
  programmatically generating a chain in contrast of reading data from storages
@@ -1532,10 +1530,10 @@ class DataChain(DatasetQuery):
1532
1530
  Parameters:
1533
1531
  to_insert : records (or a single record) to insert. Each record is
1534
1532
  a dictionary of signals and theirs values.
1533
+ schema : describes chain signals and their corresponding types
1535
1534
 
1536
1535
  Example:
1537
1536
  ```py
1538
- empty = DataChain.from_records()
1539
1537
  single_record = DataChain.from_records(DataChain.DEFAULT_FILE_RECORD)
1540
1538
  ```
1541
1539
  """
@@ -1543,11 +1541,27 @@ class DataChain(DatasetQuery):
1543
1541
  catalog = session.catalog
1544
1542
 
1545
1543
  name = session.generate_temp_dataset_name()
1546
- columns: tuple[sqlalchemy.Column[Any], ...] = tuple(
1547
- sqlalchemy.Column(name, typ)
1548
- for name, typ in File._datachain_column_types.items()
1544
+ signal_schema = None
1545
+ columns: list[sqlalchemy.Column] = []
1546
+
1547
+ if schema:
1548
+ signal_schema = SignalSchema(schema)
1549
+ columns = signal_schema.db_signals(as_columns=True) # type: ignore[assignment]
1550
+ else:
1551
+ columns = [
1552
+ sqlalchemy.Column(name, typ)
1553
+ for name, typ in File._datachain_column_types.items()
1554
+ ]
1555
+
1556
+ dsr = catalog.create_dataset(
1557
+ name,
1558
+ columns=columns,
1559
+ feature_schema=(
1560
+ signal_schema.clone_without_sys_signals().serialize()
1561
+ if signal_schema
1562
+ else None
1563
+ ),
1549
1564
  )
1550
- dsr = catalog.create_dataset(name, columns=columns)
1551
1565
 
1552
1566
  if isinstance(to_insert, dict):
1553
1567
  to_insert = [to_insert]
@@ -2,6 +2,7 @@ import copy
2
2
  from collections.abc import Iterator, Sequence
3
3
  from dataclasses import dataclass
4
4
  from datetime import datetime
5
+ from inspect import isclass
5
6
  from typing import (
6
7
  TYPE_CHECKING,
7
8
  Annotated,
@@ -14,10 +15,10 @@ from typing import (
14
15
  get_origin,
15
16
  )
16
17
 
18
+ import sqlalchemy as sa
17
19
  from pydantic import BaseModel, create_model
18
20
  from typing_extensions import Literal as LiteralEx
19
21
 
20
- from datachain.lib.convert.flatten import DATACHAIN_TO_TYPE
21
22
  from datachain.lib.convert.python_to_sql import python_to_sql
22
23
  from datachain.lib.convert.sql_to_python import sql_to_python
23
24
  from datachain.lib.convert.unflatten import unflatten_to_json_pos
@@ -26,6 +27,7 @@ from datachain.lib.file import File
26
27
  from datachain.lib.model_store import ModelStore
27
28
  from datachain.lib.utils import DataChainParamsError
28
29
  from datachain.query.schema import DEFAULT_DELIMITER, Column
30
+ from datachain.sql.types import SQLType
29
31
 
30
32
  if TYPE_CHECKING:
31
33
  from datachain.catalog import Catalog
@@ -104,12 +106,15 @@ class SignalSchema:
104
106
  def from_column_types(col_types: dict[str, Any]) -> "SignalSchema":
105
107
  signals: dict[str, DataType] = {}
106
108
  for field, col_type in col_types.items():
107
- if (py_type := DATACHAIN_TO_TYPE.get(col_type, None)) is None:
109
+ if isinstance(col_type, SQLType):
110
+ signals[field] = col_type.python_type
111
+ elif isclass(col_type) and issubclass(col_type, SQLType):
112
+ signals[field] = col_type().python_type
113
+ else:
108
114
  raise SignalSchemaError(
109
115
  f"signal schema cannot be obtained for column '{field}':"
110
- f" unsupported type '{py_type}'"
116
+ f" unsupported type '{col_type}'"
111
117
  )
112
- signals[field] = py_type
113
118
  return SignalSchema(signals)
114
119
 
115
120
  def serialize(self) -> dict[str, str]:
@@ -232,7 +237,7 @@ class SignalSchema:
232
237
  signals = [
233
238
  DEFAULT_DELIMITER.join(path)
234
239
  if not as_columns
235
- else Column(DEFAULT_DELIMITER.join(path), python_to_sql(_type))
240
+ else sa.Column(DEFAULT_DELIMITER.join(path), python_to_sql(_type))
236
241
  for path, _type, has_subtree, _ in self.get_flat_tree()
237
242
  if not has_subtree
238
243
  ]
@@ -878,17 +878,14 @@ class SQLUnion(Step):
878
878
  temp_tables.extend(self.query1.temp_table_names)
879
879
  q2 = self.query2.apply_steps().select().subquery()
880
880
  temp_tables.extend(self.query2.temp_table_names)
881
- columns1, columns2 = fill_columns(q1.columns, q2.columns)
881
+
882
+ columns1, columns2 = _order_columns(q1.columns, q2.columns)
882
883
 
883
884
  def q(*columns):
884
885
  names = {c.name for c in columns}
885
886
  col1 = [c for c in columns1 if c.name in names]
886
887
  col2 = [c for c in columns2 if c.name in names]
887
- res = (
888
- sqlalchemy.select(*col1)
889
- .select_from(q1)
890
- .union_all(sqlalchemy.select(*col2).select_from(q2))
891
- )
888
+ res = sqlalchemy.select(*col1).union_all(sqlalchemy.select(*col2))
892
889
 
893
890
  subquery = res.subquery()
894
891
  return sqlalchemy.select(*subquery.c).select_from(subquery)
@@ -1021,23 +1018,46 @@ class GroupBy(Step):
1021
1018
  return step_result(q, grouped_query.selected_columns)
1022
1019
 
1023
1020
 
1024
- def fill_columns(
1025
- *column_iterables: Iterable[ColumnElement],
1021
+ def _validate_columns(
1022
+ left_columns: Iterable[ColumnElement], right_columns: Iterable[ColumnElement]
1023
+ ) -> set[str]:
1024
+ left_names = {c.name for c in left_columns}
1025
+ right_names = {c.name for c in right_columns}
1026
+
1027
+ if left_names == right_names:
1028
+ return left_names
1029
+
1030
+ missing_right = left_names - right_names
1031
+ missing_left = right_names - left_names
1032
+
1033
+ def _prepare_msg_part(missing_columns: set[str], side: str) -> str:
1034
+ return f"{', '.join(sorted(missing_columns))} only present in {side}"
1035
+
1036
+ msg_parts = [
1037
+ _prepare_msg_part(missing_columns, found_side)
1038
+ for missing_columns, found_side in zip(
1039
+ [
1040
+ missing_right,
1041
+ missing_left,
1042
+ ],
1043
+ ["left", "right"],
1044
+ )
1045
+ if missing_columns
1046
+ ]
1047
+ msg = f"Cannot perform union. {'. '.join(msg_parts)}"
1048
+
1049
+ raise ValueError(msg)
1050
+
1051
+
1052
+ def _order_columns(
1053
+ left_columns: Iterable[ColumnElement], right_columns: Iterable[ColumnElement]
1026
1054
  ) -> list[list[ColumnElement]]:
1027
- column_dicts = [{c.name: c for c in columns} for columns in column_iterables]
1028
- combined_columns = {n: c for col_dict in column_dicts for n, c in col_dict.items()}
1029
-
1030
- result: list[list[ColumnElement]] = [[] for _ in column_dicts]
1031
- for n in combined_columns:
1032
- col = next(col_dict[n] for col_dict in column_dicts if n in col_dict)
1033
- for col_dict, out in zip(column_dicts, result):
1034
- if n in col_dict:
1035
- out.append(col_dict[n])
1036
- else:
1037
- # Cast the NULL to ensure all columns are aware of their type
1038
- # Label it to ensure it's aware of its name
1039
- out.append(sqlalchemy.cast(sqlalchemy.null(), col.type).label(n))
1040
- return result
1055
+ column_order = _validate_columns(left_columns, right_columns)
1056
+ column_dicts = [
1057
+ {c.name: c for c in columns} for columns in [left_columns, right_columns]
1058
+ ]
1059
+
1060
+ return [[d[n] for n in column_order] for d in column_dicts]
1041
1061
 
1042
1062
 
1043
1063
  @attrs.define
datachain/sql/types.py CHANGED
@@ -20,6 +20,8 @@ from typing import Any, Union
20
20
  import sqlalchemy as sa
21
21
  from sqlalchemy import TypeDecorator, types
22
22
 
23
+ from datachain.lib.data_model import StandardType
24
+
23
25
  _registry: dict[str, "TypeConverter"] = {}
24
26
  registry = MappingProxyType(_registry)
25
27
 
@@ -91,6 +93,10 @@ class SQLType(TypeDecorator):
91
93
  impl: type[types.TypeEngine[Any]] = types.TypeEngine
92
94
  cache_ok = True
93
95
 
96
+ @property
97
+ def python_type(self) -> StandardType:
98
+ raise NotImplementedError
99
+
94
100
  def to_dict(self) -> dict[str, Any]:
95
101
  return {"type": self.__class__.__name__}
96
102
 
@@ -103,7 +109,7 @@ class String(SQLType):
103
109
  impl = types.String
104
110
 
105
111
  @property
106
- def python_type(self):
112
+ def python_type(self) -> StandardType:
107
113
  return str
108
114
 
109
115
  def load_dialect_impl(self, dialect):
@@ -125,7 +131,7 @@ class Boolean(SQLType):
125
131
  impl = types.Boolean
126
132
 
127
133
  @property
128
- def python_type(self):
134
+ def python_type(self) -> StandardType:
129
135
  return bool
130
136
 
131
137
  def load_dialect_impl(self, dialect):
@@ -147,7 +153,7 @@ class Int(SQLType):
147
153
  impl = types.INTEGER
148
154
 
149
155
  @property
150
- def python_type(self):
156
+ def python_type(self) -> StandardType:
151
157
  return int
152
158
 
153
159
  def load_dialect_impl(self, dialect):
@@ -217,7 +223,7 @@ class Float(SQLType):
217
223
  impl = types.FLOAT
218
224
 
219
225
  @property
220
- def python_type(self):
226
+ def python_type(self) -> StandardType:
221
227
  return float
222
228
 
223
229
  def load_dialect_impl(self, dialect):
@@ -271,7 +277,7 @@ class Array(SQLType):
271
277
  impl = types.ARRAY
272
278
 
273
279
  @property
274
- def python_type(self):
280
+ def python_type(self) -> StandardType:
275
281
  return list
276
282
 
277
283
  def load_dialect_impl(self, dialect):
@@ -314,7 +320,7 @@ class JSON(SQLType):
314
320
  impl = types.JSON
315
321
 
316
322
  @property
317
- def python_type(self):
323
+ def python_type(self) -> StandardType:
318
324
  return dict
319
325
 
320
326
  def load_dialect_impl(self, dialect):
@@ -336,7 +342,7 @@ class DateTime(SQLType):
336
342
  impl = types.DATETIME
337
343
 
338
344
  @property
339
- def python_type(self):
345
+ def python_type(self) -> StandardType:
340
346
  return datetime
341
347
 
342
348
  def load_dialect_impl(self, dialect):
@@ -358,7 +364,7 @@ class Binary(SQLType):
358
364
  impl = types.BINARY
359
365
 
360
366
  @property
361
- def python_type(self):
367
+ def python_type(self) -> StandardType:
362
368
  return bytes
363
369
 
364
370
  def load_dialect_impl(self, dialect):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: datachain
3
- Version: 0.3.4
3
+ Version: 0.3.5
4
4
  Summary: Wrangle unstructured AI data at scale
5
5
  Author-email: Dmitry Petrov <support@dvc.org>
6
6
  License: Apache-2.0
@@ -40,6 +40,7 @@ Requires-Dist: pydantic <3,>=2
40
40
  Requires-Dist: jmespath >=1.0
41
41
  Requires-Dist: datamodel-code-generator >=0.25
42
42
  Requires-Dist: Pillow <11,>=10.0.0
43
+ Requires-Dist: msgpack <2,>=1.0.4
43
44
  Requires-Dist: numpy <2,>=1 ; sys_platform == "win32"
44
45
  Provides-Extra: dev
45
46
  Requires-Dist: datachain[docs,tests] ; extra == 'dev'
@@ -61,12 +62,10 @@ Requires-Dist: numpy <2,>=1 ; extra == 'examples'
61
62
  Requires-Dist: defusedxml ; extra == 'examples'
62
63
  Requires-Dist: accelerate ; extra == 'examples'
63
64
  Requires-Dist: unstructured[pdf] ; extra == 'examples'
64
- Requires-Dist: pdfplumber ==0.11.3 ; extra == 'examples'
65
+ Requires-Dist: pdfplumber ==0.11.4 ; extra == 'examples'
65
66
  Requires-Dist: huggingface-hub[hf_transfer] ; extra == 'examples'
66
- Requires-Dist: nltk ==3.8.1 ; extra == 'examples'
67
67
  Provides-Extra: remote
68
68
  Requires-Dist: lz4 ; extra == 'remote'
69
- Requires-Dist: msgpack <2,>=1.0.4 ; extra == 'remote'
70
69
  Requires-Dist: requests >=2.22.0 ; extra == 'remote'
71
70
  Provides-Extra: tests
72
71
  Requires-Dist: datachain[remote,torch,vector] ; extra == 'tests'
@@ -42,7 +42,7 @@ datachain/lib/arrow.py,sha256=D8N7zCppRdc5sTYT1hNIbROc-sKA_8FN5J_m-KjD3Us,4929
42
42
  datachain/lib/clip.py,sha256=16u4b_y2Y15nUS2UN_8ximMo6r_-_4IQpmct2ol-e-g,5730
43
43
  datachain/lib/data_model.py,sha256=ZvtMRMcPpBxI-rOhkXb-ry1PkGYcEFFK1w1wH12vs4g,1718
44
44
  datachain/lib/dataset_info.py,sha256=lONGr71ozo1DS4CQEhnpKORaU4qFb6Ketv8Xm8CVm2U,2188
45
- datachain/lib/dc.py,sha256=0pwNb91GW8MnHLfFd2YvEtEH0n77c3nxp5ozwIyW86o,58827
45
+ datachain/lib/dc.py,sha256=atGpaeCUwxDEgHIFmWqG1rAnqe7utT6S7c1jM5yVb7c,59246
46
46
  datachain/lib/file.py,sha256=ZHpdilDPYCob8uqtwUPtBvBNxVvQRq4AC_0IGg5m-G4,12003
47
47
  datachain/lib/image.py,sha256=TgYhRhzd4nkytfFMeykQkPyzqb5Le_-tU81unVMPn4Q,2328
48
48
  datachain/lib/listing.py,sha256=nXLmGae_oQke4hnurzzWiHTEjHjWiqqHdB41Wb-hMTk,3521
@@ -50,7 +50,7 @@ datachain/lib/meta_formats.py,sha256=Hels85LJmNCz1aYVJvhymNdAt3qdJ2-qoxsIiUezrow
50
50
  datachain/lib/model_store.py,sha256=c4USXsBBjrGH8VOh4seIgOiav-qHOwdoixtxfLgU63c,2409
51
51
  datachain/lib/pytorch.py,sha256=9PsypKseyKfIimTmTQOgb-pbNXgeeAHLdlWx0qRPULY,5660
52
52
  datachain/lib/settings.py,sha256=39thOpYJw-zPirzeNO6pmRC2vPrQvt4eBsw1xLWDFsw,2344
53
- datachain/lib/signal_schema.py,sha256=VL9TR0CJ3eRzjIDr-8e-e7cZKuMBbPUZtY2lGAsucc0,15734
53
+ datachain/lib/signal_schema.py,sha256=MS8qkOIl-3Qh3KyYTCtuSgF9nP5PeaGccbtGqfWo2wI,15902
54
54
  datachain/lib/text.py,sha256=dVe2Ilc_gW2EV0kun0UwegiCkapWcd20cef7CgINWHU,1083
55
55
  datachain/lib/udf.py,sha256=n3x6No-7l5LAciPJPWwZbA8WtTnGUU7d0wRL6CyfZh8,11847
56
56
  datachain/lib/udf_signature.py,sha256=gMStcEeYJka5M6cg50Z9orC6y6HzCAJ3MkFqqn1fjZg,7137
@@ -59,7 +59,7 @@ datachain/lib/vfile.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
59
59
  datachain/lib/webdataset.py,sha256=SsjCKLSKEkHRRfeTHQhjoGqNPqIWw_SCWQcUwgUWWP0,8282
60
60
  datachain/lib/webdataset_laion.py,sha256=PQP6tQmUP7Xu9fPuAGK1JDBYA6T5UufYMUTGaxgspJA,2118
61
61
  datachain/lib/convert/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
62
- datachain/lib/convert/flatten.py,sha256=YMoC00BqEy3zSpvCp6Q0DfxihuPmgjUJj1g2cesWGPs,1790
62
+ datachain/lib/convert/flatten.py,sha256=Uebc5CeqCsacp-nr6IG9i6OGuUavXqdqnoGctZBk3RQ,1384
63
63
  datachain/lib/convert/python_to_sql.py,sha256=4gplGlr_Kg-Z40OpJUzJiarDWj7pwbUOk-dPOYYCJ9Q,2629
64
64
  datachain/lib/convert/sql_to_python.py,sha256=lGnKzSF_tz9Y_5SSKkrIU95QEjpcDzvOxIRkEKTQag0,443
65
65
  datachain/lib/convert/unflatten.py,sha256=Ogvh_5wg2f38_At_1lN0D_e2uZOOpYEvwvB2xdq56Tw,2012
@@ -67,7 +67,7 @@ datachain/lib/convert/values_to_tuples.py,sha256=YOdbjzHq-uj6-cV2Qq43G72eN2avMND
67
67
  datachain/query/__init__.py,sha256=tv-spkjUCYamMN9ys_90scYrZ8kJ7C7d1MTYVmxGtk4,325
68
68
  datachain/query/batch.py,sha256=-vlpINJiertlnaoUVv1C95RatU0F6zuhpIYRufJRo1M,3660
69
69
  datachain/query/builtins.py,sha256=EmKPYsoQ46zwdyOn54MuCzvYFmfsBn5F8zyF7UBUfrc,2550
70
- datachain/query/dataset.py,sha256=7lxlybS7I5IPsgOqMz-W4vS6kWBDHkHQRqBHlIRYRPw,60473
70
+ datachain/query/dataset.py,sha256=4F_Q101Lbpc0YxOAcP3rc3GtKv8HwxpqF9lpJ0OoUEk,60818
71
71
  datachain/query/dispatch.py,sha256=GBh3EZHDp5AaXxrjOpfrpfsuy7Umnqxu-MAXcK9X3gc,12945
72
72
  datachain/query/metrics.py,sha256=vsECqbZfoSDBnvC3GQlziKXmISVYDLgHP1fMPEOtKyo,640
73
73
  datachain/query/params.py,sha256=O_j89mjYRLOwWNhYZl-z7mi-rkdP7WyFmaDufsdTryE,863
@@ -79,7 +79,7 @@ datachain/remote/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,
79
79
  datachain/remote/studio.py,sha256=f5s6qSZ9uB4URGUoU_8_W1KZRRQQVSm6cgEBkBUEfuE,7226
80
80
  datachain/sql/__init__.py,sha256=A2djrbQwSMUZZEIKGnm-mnRA-NDSbiDJNpAmmwGNyIo,303
81
81
  datachain/sql/selectable.py,sha256=fBM-wS1TUA42kVEAAiwqGtibIevyZAEritwt8PZGyLQ,1589
82
- datachain/sql/types.py,sha256=1MFvECB_5A6QwQKKY3VPhvitgKDlc2aB7iBjY4hv1_s,13034
82
+ datachain/sql/types.py,sha256=1ofJjgzKTxFLl1WaMSI9pLvdHGZ1U24I0z5i-gChqDI,13305
83
83
  datachain/sql/utils.py,sha256=rzlJw08etivdrcuQPqNVvVWhuVSyUPUQEEc6DOhu258,818
84
84
  datachain/sql/default/__init__.py,sha256=XQ2cEZpzWiABqjV-6yYHUBGI9vN_UHxbxZENESmVAWw,45
85
85
  datachain/sql/default/base.py,sha256=QD-31C6JnyOXzogyDx90sUhm7QvgXIYpeHEASH84igU,628
@@ -94,9 +94,9 @@ datachain/sql/sqlite/base.py,sha256=WLPHBhZbXbiqPoRV1VgDrXJqku4UuvJpBhYeQ0k5rI8,
94
94
  datachain/sql/sqlite/types.py,sha256=yzvp0sXSEoEYXs6zaYC_2YubarQoZH-MiUNXcpuEP4s,1573
95
95
  datachain/sql/sqlite/vector.py,sha256=ncW4eu2FlJhrP_CIpsvtkUabZlQdl2D5Lgwy_cbfqR0,469
96
96
  datachain/torch/__init__.py,sha256=gIS74PoEPy4TB3X6vx9nLO0Y3sLJzsA8ckn8pRWihJM,579
97
- datachain-0.3.4.dist-info/LICENSE,sha256=8DnqK5yoPI_E50bEg_zsHKZHY2HqPy4rYN338BHQaRA,11344
98
- datachain-0.3.4.dist-info/METADATA,sha256=nV1-yJcDxoWuaM8uSwEzYCpDqSMxhxPle3EZZ98a-LA,16789
99
- datachain-0.3.4.dist-info/WHEEL,sha256=nCVcAvsfA9TDtwGwhYaRrlPhTLV9m-Ga6mdyDtuwK18,91
100
- datachain-0.3.4.dist-info/entry_points.txt,sha256=0GMJS6B_KWq0m3VT98vQI2YZodAMkn4uReZ_okga9R4,49
101
- datachain-0.3.4.dist-info/top_level.txt,sha256=lZPpdU_2jJABLNIg2kvEOBi8PtsYikbN1OdMLHk8bTg,10
102
- datachain-0.3.4.dist-info/RECORD,,
97
+ datachain-0.3.5.dist-info/LICENSE,sha256=8DnqK5yoPI_E50bEg_zsHKZHY2HqPy4rYN338BHQaRA,11344
98
+ datachain-0.3.5.dist-info/METADATA,sha256=SaQj0C0_Ugll_S1RTRCkFM4U1fZwC7bweiaQZhovqcs,16719
99
+ datachain-0.3.5.dist-info/WHEEL,sha256=Mdi9PDNwEZptOjTlUcAth7XJDFtKrHYaQMPulZeBCiQ,91
100
+ datachain-0.3.5.dist-info/entry_points.txt,sha256=0GMJS6B_KWq0m3VT98vQI2YZodAMkn4uReZ_okga9R4,49
101
+ datachain-0.3.5.dist-info/top_level.txt,sha256=lZPpdU_2jJABLNIg2kvEOBi8PtsYikbN1OdMLHk8bTg,10
102
+ datachain-0.3.5.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (73.0.0)
2
+ Generator: setuptools (73.0.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5