microdf-python 1.2.0__py3-none-any.whl → 1.2.2__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.
microdf/microdataframe.py CHANGED
@@ -278,18 +278,18 @@ class MicroDataFrame(pd.DataFrame):
278
278
  self._link_all_weights()
279
279
 
280
280
  def _link_weights(self, column) -> None:
281
- # self[column] = ... triggers __setitem__, which forces pd.Series
282
- # this workaround avoids that
283
- self[column].__class__ = MicroSeries
284
- self[column].set_weights(self.weights)
281
+ # In pandas 3.0+, we can't modify column classes in-place due to CoW.
282
+ # Instead, we rely on __getitem__ to wrap columns as MicroSeries on
283
+ # access. This method is kept for backward compatibility but is now
284
+ # a no-op.
285
+ pass
285
286
 
286
287
  def _link_all_weights(self) -> None:
287
288
  if self.weights is None:
288
289
  if len(self) > 0:
289
290
  self.set_weights(np.ones((len(self))))
290
- for column in self.columns:
291
- if column != self.weights_col:
292
- self._link_weights(column)
291
+ # In pandas 3.0+, columns are wrapped as MicroSeries on access via
292
+ # __getitem__, not stored as MicroSeries internally.
293
293
 
294
294
  def set_weights(
295
295
  self,
@@ -365,7 +365,7 @@ class MicroDataFrame(pd.DataFrame):
365
365
 
366
366
  def __getitem__(
367
367
  self, key: Union[str, List]
368
- ) -> Union[pd.Series, pd.DataFrame]:
368
+ ) -> Union[MicroSeries, "MicroDataFrame"]:
369
369
  # Let pandas handle the initial slicing
370
370
  result = super().__getitem__(key)
371
371
 
@@ -374,17 +374,22 @@ class MicroDataFrame(pd.DataFrame):
374
374
  new_weights = self.weights.reindex(result.index)
375
375
  return MicroDataFrame(result, weights=new_weights)
376
376
 
377
- # Otherwise, the result is a Series or a scalar, so just return it
377
+ # If the result is a Series (single column), wrap as MicroSeries
378
+ if isinstance(result, pd.Series):
379
+ return MicroSeries(result, weights=self.weights)
380
+
381
+ # Otherwise, the result is a scalar, so just return it
378
382
  return result
379
383
 
380
384
  def catch_series_relapse(self) -> None:
381
- for col in self.columns:
382
- if self[col].__class__ == pd.Series:
383
- self._link_weights(col)
385
+ # In pandas 3.0+, we don't need to track series class changes since
386
+ # __getitem__ always wraps columns as MicroSeries on access.
387
+ pass
384
388
 
385
389
  def __setattr__(self, key, value) -> None:
386
390
  super().__setattr__(key, value)
387
- self.catch_series_relapse()
391
+ # No need to call catch_series_relapse in pandas 3.0+ since we wrap
392
+ # on access rather than store MicroSeries internally.
388
393
 
389
394
  def reset_index(
390
395
  self,
microdf/microseries.py CHANGED
@@ -1,4 +1,5 @@
1
1
  import logging
2
+ import warnings
2
3
  from functools import wraps
3
4
  from typing import Callable, List, Optional, Union
4
5
 
@@ -19,6 +20,50 @@ class MicroSeries(pd.Series):
19
20
  super().__init__(*args, **kwargs)
20
21
  self.set_weights(weights)
21
22
 
23
+ @property
24
+ def _values(self):
25
+ """Internal access to underlying numpy array without warning."""
26
+ return super().values
27
+
28
+ @property
29
+ def values(self):
30
+ """Access underlying numpy array.
31
+
32
+ .. warning::
33
+ Returns a plain numpy array without weights. Operations
34
+ like ``.mean()`` on the result will be unweighted. Use
35
+ MicroSeries methods directly for weighted calculations
36
+ (e.g., ``ms.mean()`` instead of ``ms.values.mean()``).
37
+ """
38
+ warnings.warn(
39
+ "Accessing .values on a MicroSeries returns a plain numpy "
40
+ "array without weights. Operations like .mean() on the "
41
+ "result will be unweighted. Use MicroSeries methods "
42
+ "directly for weighted calculations (e.g., ms.mean() "
43
+ "instead of ms.values.mean()).",
44
+ UserWarning,
45
+ stacklevel=2,
46
+ )
47
+ return super().values
48
+
49
+ def to_numpy(self, *args, **kwargs):
50
+ """Convert to numpy array.
51
+
52
+ .. warning::
53
+ Returns a plain numpy array without weights. Operations
54
+ like ``.mean()`` on the result will be unweighted. Use
55
+ MicroSeries methods directly for weighted calculations.
56
+ """
57
+ warnings.warn(
58
+ "Calling .to_numpy() on a MicroSeries returns a plain "
59
+ "numpy array without weights. Operations like .mean() on "
60
+ "the result will be unweighted. Use MicroSeries methods "
61
+ "directly for weighted calculations.",
62
+ UserWarning,
63
+ stacklevel=2,
64
+ )
65
+ return super().to_numpy(*args, **kwargs)
66
+
22
67
  def weighted_function(fn: Callable) -> Callable:
23
68
  @wraps(fn)
24
69
  def safe_fn(*args, **kwargs):
@@ -52,7 +97,7 @@ class MicroSeries(pd.Series):
52
97
  if weights is None:
53
98
  if len(self) > 0:
54
99
  self.weights = pd.Series(
55
- np.ones_like(self.values), dtype=float
100
+ np.ones_like(self._values), dtype=float
56
101
  )
57
102
  else:
58
103
  if len(weights) != len(self):
@@ -110,7 +155,7 @@ class MicroSeries(pd.Series):
110
155
  :returns: The weighted mean.
111
156
  :rtype: float
112
157
  """
113
- values = self.values
158
+ values = self._values
114
159
  weights = self.weights
115
160
 
116
161
  if skipna:
@@ -141,7 +186,7 @@ class MicroSeries(pd.Series):
141
186
  :return: Weighted quantile value(s).
142
187
  :rtype: float or pd.Series
143
188
  """
144
- values = np.array(self.values)
189
+ values = np.array(self._values)
145
190
  quantiles = np.atleast_1d(q)
146
191
  sample_weight = np.array(self.weights)
147
192
  assert np.all(quantiles >= 0) and np.all(
@@ -313,7 +358,7 @@ class MicroSeries(pd.Series):
313
358
  "in division by zero."
314
359
  )
315
360
 
316
- order = np.argsort(self.values)
361
+ order = np.argsort(self._values)
317
362
  inverse_order = np.argsort(order)
318
363
  ranks = np.array(self.weights.values)[order].cumsum()[inverse_order]
319
364
  if pct:
@@ -506,7 +551,7 @@ class MicroSeries(pd.Series):
506
551
  return MicroSeries(super().__rxor__(other), weights=self.weights)
507
552
 
508
553
  def sqrt(self) -> "MicroSeries":
509
- sqrt_values = np.sqrt(self.values)
554
+ sqrt_values = np.sqrt(self._values)
510
555
  return MicroSeries(sqrt_values, index=self.index, weights=self.weights)
511
556
 
512
557
  # comparators
@@ -590,7 +635,7 @@ class MicroSeries(pd.Series):
590
635
 
591
636
  def __repr__(self) -> str:
592
637
  return pd.DataFrame(
593
- dict(value=self.values, weight=self.weights.values)
638
+ dict(value=self._values, weight=self.weights.values)
594
639
  ).__repr__()
595
640
 
596
641
 
@@ -1,3 +1,5 @@
1
+ import warnings
2
+
1
3
  import numpy as np
2
4
  import pandas as pd
3
5
 
@@ -423,3 +425,45 @@ def test_groupby_column_selection() -> None:
423
425
  result_all = d.groupby("g").sum()
424
426
  assert "weight" not in result_all.columns
425
427
  assert list(result_all.columns) == ["y"]
428
+
429
+
430
+ def test_values_warns() -> None:
431
+ """Accessing .values on a MicroSeries should emit a UserWarning."""
432
+ ms = mdf.MicroSeries([1, 2, 3], weights=[4, 5, 6])
433
+ with warnings.catch_warnings(record=True) as w:
434
+ warnings.simplefilter("always")
435
+ _ = ms.values
436
+ assert len(w) == 1
437
+ assert issubclass(w[0].category, UserWarning)
438
+ assert "weights" in str(w[0].message).lower()
439
+
440
+
441
+ def test_to_numpy_warns() -> None:
442
+ """Calling .to_numpy() on a MicroSeries should emit a UserWarning."""
443
+ ms = mdf.MicroSeries([1, 2, 3], weights=[4, 5, 6])
444
+ with warnings.catch_warnings(record=True) as w:
445
+ warnings.simplefilter("always")
446
+ _ = ms.to_numpy()
447
+ assert len(w) == 1
448
+ assert issubclass(w[0].category, UserWarning)
449
+ assert "weights" in str(w[0].message).lower()
450
+
451
+
452
+ def test_mean_no_warning() -> None:
453
+ """Internal .values usage in .mean() should NOT emit a warning."""
454
+ ms = mdf.MicroSeries([1, 2, 3], weights=[4, 5, 6])
455
+ with warnings.catch_warnings(record=True) as w:
456
+ warnings.simplefilter("always")
457
+ _ = ms.mean()
458
+ user_warnings = [x for x in w if issubclass(x.category, UserWarning)]
459
+ assert len(user_warnings) == 0
460
+
461
+
462
+ def test_repr_no_warning() -> None:
463
+ """Internal .values usage in __repr__ should NOT emit a warning."""
464
+ ms = mdf.MicroSeries([1, 2, 3], weights=[4, 5, 6])
465
+ with warnings.catch_warnings(record=True) as w:
466
+ warnings.simplefilter("always")
467
+ _ = repr(ms)
468
+ user_warnings = [x for x in w if issubclass(x.category, UserWarning)]
469
+ assert len(user_warnings) == 0
@@ -1,5 +1,4 @@
1
- """
2
- Tests for pandas 3.0.0 compatibility in microdf.
1
+ """Tests for pandas 3.0.0 compatibility in microdf.
3
2
 
4
3
  These tests verify that microdf works correctly with pandas 3.0.0,
5
4
  which introduces:
@@ -10,18 +9,17 @@ which introduces:
10
9
 
11
10
  import numpy as np
12
11
  import pandas as pd
13
- import pytest
14
12
 
15
- from microdf.microseries import MicroSeries
16
13
  from microdf.microdataframe import MicroDataFrame
14
+ from microdf.microseries import MicroSeries
17
15
 
18
16
 
19
17
  class TestMicroSeriesSubclassPreservation:
20
18
  """Test that MicroSeries subclass is preserved across operations."""
21
19
 
22
20
  def test_microseries_set_weights_after_creation(self):
23
- """
24
- Ensure set_weights works on MicroSeries.
21
+ """Ensure set_weights works on MicroSeries.
22
+
25
23
  This is the error reported in pandas 3:
26
24
  AttributeError: 'Series' object has no attribute 'set_weights'
27
25
  """
@@ -34,86 +32,97 @@ class TestMicroSeriesSubclassPreservation:
34
32
  assert np.allclose(ms.weights, [2.0, 2.0, 2.0])
35
33
 
36
34
  def test_microseries_preserved_after_arithmetic(self):
37
- """
38
- Arithmetic operations should return MicroSeries, not plain Series.
39
- """
35
+ """Arithmetic operations should return MicroSeries, not plain
36
+ Series."""
40
37
  ms = MicroSeries([1, 2, 3], weights=np.array([1.0, 2.0, 3.0]))
41
38
 
42
39
  # Addition
43
40
  result = ms + 1
44
- assert isinstance(result, MicroSeries), f"Got {type(result)} instead of MicroSeries"
41
+ assert isinstance(
42
+ result, MicroSeries
43
+ ), f"Got {type(result)} instead of MicroSeries"
45
44
  assert hasattr(result, "weights")
46
45
  assert hasattr(result, "set_weights")
47
46
 
48
47
  # Multiplication
49
48
  result = ms * 2
50
- assert isinstance(result, MicroSeries), f"Got {type(result)} instead of MicroSeries"
49
+ assert isinstance(
50
+ result, MicroSeries
51
+ ), f"Got {type(result)} instead of MicroSeries"
51
52
 
52
53
  # Division
53
54
  result = ms / 2
54
- assert isinstance(result, MicroSeries), f"Got {type(result)} instead of MicroSeries"
55
+ assert isinstance(
56
+ result, MicroSeries
57
+ ), f"Got {type(result)} instead of MicroSeries"
55
58
 
56
59
  def test_microseries_preserved_after_comparison(self):
57
- """
58
- Comparison operations should return MicroSeries, not plain Series.
59
- """
60
+ """Comparison operations should return MicroSeries, not plain
61
+ Series."""
60
62
  ms = MicroSeries([1, 2, 3], weights=np.array([1.0, 2.0, 3.0]))
61
63
 
62
64
  # Greater than
63
65
  result = ms > 1
64
- assert isinstance(result, MicroSeries), f"Got {type(result)} instead of MicroSeries"
66
+ assert isinstance(
67
+ result, MicroSeries
68
+ ), f"Got {type(result)} instead of MicroSeries"
65
69
  assert hasattr(result, "weights")
66
70
 
67
71
  # Less than
68
72
  result = ms < 3
69
- assert isinstance(result, MicroSeries), f"Got {type(result)} instead of MicroSeries"
73
+ assert isinstance(
74
+ result, MicroSeries
75
+ ), f"Got {type(result)} instead of MicroSeries"
70
76
 
71
77
  def test_microseries_preserved_after_indexing(self):
72
- """
73
- Indexing operations should return MicroSeries, not plain Series.
74
- """
75
- ms = MicroSeries([1, 2, 3, 4, 5], weights=np.array([1.0, 2.0, 3.0, 4.0, 5.0]))
78
+ """Indexing operations should return MicroSeries, not plain Series."""
79
+ ms = MicroSeries(
80
+ [1, 2, 3, 4, 5], weights=np.array([1.0, 2.0, 3.0, 4.0, 5.0])
81
+ )
76
82
 
77
83
  # Boolean indexing
78
84
  result = ms[ms > 2]
79
- assert isinstance(result, MicroSeries), f"Got {type(result)} instead of MicroSeries"
85
+ assert isinstance(
86
+ result, MicroSeries
87
+ ), f"Got {type(result)} instead of MicroSeries"
80
88
  assert hasattr(result, "weights")
81
89
 
82
90
  # Slice indexing
83
91
  result = ms[1:3]
84
- assert isinstance(result, MicroSeries), f"Got {type(result)} instead of MicroSeries"
92
+ assert isinstance(
93
+ result, MicroSeries
94
+ ), f"Got {type(result)} instead of MicroSeries"
85
95
 
86
96
 
87
97
  class TestMicroDataFrameSubclassPreservation:
88
98
  """Test that MicroDataFrame column access returns MicroSeries."""
89
99
 
90
100
  def test_microdataframe_column_returns_microseries(self):
91
- """
92
- Accessing a column from MicroDataFrame should return MicroSeries.
93
- """
101
+ """Accessing a column from MicroDataFrame should return MicroSeries."""
94
102
  mdf = MicroDataFrame(
95
- {"a": [1, 2, 3], "b": [4, 5, 6]},
96
- weights=np.array([1.0, 2.0, 3.0])
103
+ {"a": [1, 2, 3], "b": [4, 5, 6]}, weights=np.array([1.0, 2.0, 3.0])
97
104
  )
98
105
 
99
106
  # Column access
100
107
  col = mdf["a"]
101
- assert isinstance(col, MicroSeries), f"Got {type(col)} instead of MicroSeries"
108
+ assert isinstance(
109
+ col, MicroSeries
110
+ ), f"Got {type(col)} instead of MicroSeries"
102
111
  assert hasattr(col, "weights")
103
112
  assert hasattr(col, "set_weights")
104
113
 
105
114
  def test_microdataframe_operations_preserve_type(self):
106
- """
107
- Operations on MicroDataFrame columns should preserve MicroSeries type.
108
- """
115
+ """Operations on MicroDataFrame columns should preserve MicroSeries
116
+ type."""
109
117
  mdf = MicroDataFrame(
110
- {"a": [1, 2, 3], "b": [4, 5, 6]},
111
- weights=np.array([1.0, 2.0, 3.0])
118
+ {"a": [1, 2, 3], "b": [4, 5, 6]}, weights=np.array([1.0, 2.0, 3.0])
112
119
  )
113
120
 
114
121
  # Column operations
115
122
  result = mdf["a"] + mdf["b"]
116
- assert isinstance(result, MicroSeries), f"Got {type(result)} instead of MicroSeries"
123
+ assert isinstance(
124
+ result, MicroSeries
125
+ ), f"Got {type(result)} instead of MicroSeries"
117
126
  assert hasattr(result, "weights")
118
127
 
119
128
 
@@ -121,21 +130,17 @@ class TestStringDtypeHandling:
121
130
  """Test that MicroSeries/MicroDataFrame handle pandas 3 string dtypes."""
122
131
 
123
132
  def test_microseries_with_string_data(self):
124
- """
125
- MicroSeries should work with string data in pandas 3.
126
- """
133
+ """MicroSeries should work with string data in pandas 3."""
127
134
  # Create with string data
128
135
  ms = MicroSeries(["a", "b", "c"], weights=np.array([1.0, 2.0, 3.0]))
129
136
  assert len(ms) == 3
130
137
  assert hasattr(ms, "weights")
131
138
 
132
139
  def test_microdataframe_with_string_columns(self):
133
- """
134
- MicroDataFrame should work with string columns in pandas 3.
135
- """
140
+ """MicroDataFrame should work with string columns in pandas 3."""
136
141
  mdf = MicroDataFrame(
137
142
  {"names": ["alice", "bob", "charlie"], "values": [1, 2, 3]},
138
- weights=np.array([1.0, 2.0, 3.0])
143
+ weights=np.array([1.0, 2.0, 3.0]),
139
144
  )
140
145
  assert len(mdf) == 3
141
146
 
@@ -169,9 +174,7 @@ class TestCopyOnWriteCompatibility:
169
174
  """Test compatibility with pandas 3 Copy-on-Write."""
170
175
 
171
176
  def test_microseries_copy_independent(self):
172
- """
173
- Copying a MicroSeries should create an independent copy.
174
- """
177
+ """Copying a MicroSeries should create an independent copy."""
175
178
  ms = MicroSeries([1, 2, 3], weights=np.array([1.0, 2.0, 3.0]))
176
179
  ms_copy = ms.copy()
177
180
 
@@ -182,12 +185,9 @@ class TestCopyOnWriteCompatibility:
182
185
  assert np.allclose(ms_copy.weights, [1.0, 2.0, 3.0])
183
186
 
184
187
  def test_microdataframe_copy_independent(self):
185
- """
186
- Copying a MicroDataFrame should create an independent copy.
187
- """
188
+ """Copying a MicroDataFrame should create an independent copy."""
188
189
  mdf = MicroDataFrame(
189
- {"a": [1, 2, 3]},
190
- weights=np.array([1.0, 2.0, 3.0])
190
+ {"a": [1, 2, 3]}, weights=np.array([1.0, 2.0, 3.0])
191
191
  )
192
192
  mdf_copy = mdf.copy()
193
193
 
@@ -197,14 +197,32 @@ class TestCopyOnWriteCompatibility:
197
197
  # Copy should be unchanged
198
198
  assert np.allclose(mdf_copy.weights, [1.0, 2.0, 3.0])
199
199
 
200
+ def test_column_set_weights_after_access_regression(self):
201
+ """Regression test for pandas 3.0 CoW compatibility.
202
+
203
+ In pandas 3.0 with Copy-on-Write, modifying column.__class__ doesn't
204
+ persist because each access returns a copy. This test verifies the fix
205
+ that wraps columns as MicroSeries on access in __getitem__.
206
+ """
207
+ mdf = MicroDataFrame(
208
+ {"income": [10000, 20000, 30000]},
209
+ weights=np.array([1.0, 2.0, 3.0]),
210
+ )
211
+
212
+ # This was the exact error that occurred:
213
+ # AttributeError: 'Series' object has no attribute 'set_weights'
214
+ col = mdf["income"]
215
+ col.set_weights(np.array([4.0, 5.0, 6.0])) # Would fail before fix
216
+
217
+ # Verify the new weights took effect
218
+ assert np.allclose(col.weights, [4.0, 5.0, 6.0])
219
+
200
220
 
201
221
  class TestGroupByWithPandas3:
202
222
  """Test groupby operations with pandas 3."""
203
223
 
204
224
  def test_microseries_groupby_preserves_weights(self):
205
- """
206
- GroupBy operations should preserve weights.
207
- """
225
+ """GroupBy operations should preserve weights."""
208
226
  ms = MicroSeries([1, 2, 3, 4], weights=np.array([1.0, 2.0, 3.0, 4.0]))
209
227
  groups = pd.Series(["a", "a", "b", "b"])
210
228
 
@@ -217,12 +235,10 @@ class TestGroupByWithPandas3:
217
235
  assert result["b"] == 25
218
236
 
219
237
  def test_microdataframe_groupby_preserves_weights(self):
220
- """
221
- MicroDataFrame groupby should preserve weights on columns.
222
- """
238
+ """MicroDataFrame groupby should preserve weights on columns."""
223
239
  mdf = MicroDataFrame(
224
240
  {"group": ["a", "a", "b", "b"], "value": [1, 2, 3, 4]},
225
- weights=np.array([1.0, 2.0, 3.0, 4.0])
241
+ weights=np.array([1.0, 2.0, 3.0, 4.0]),
226
242
  )
227
243
 
228
244
  gb = mdf.groupby("group")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: microdf-python
3
- Version: 1.2.0
3
+ Version: 1.2.2
4
4
  Summary: Weighted pandas DataFrames and Series for survey microdata
5
5
  Author-email: Max Ghenis <max@policyengine.org>
6
6
  License: MIT
@@ -20,6 +20,7 @@ Requires-Dist: linecheck; extra == "dev"
20
20
  Requires-Dist: pytest; extra == "dev"
21
21
  Requires-Dist: pytest-cov; extra == "dev"
22
22
  Requires-Dist: setuptools; extra == "dev"
23
+ Requires-Dist: towncrier>=24.8.0; extra == "dev"
23
24
  Dynamic: license-file
24
25
 
25
26
  [![Build](https://github.com/PolicyEngine/microdf/workflows/Pull%20request/badge.svg)](https://github.com/PolicyEngine/microdf/actions)
@@ -0,0 +1,11 @@
1
+ microdf/__init__.py,sha256=ldRvhE8t4cD7qlxQ5yLndMnWEUYpDw4m-jCDV_psXkY,319
2
+ microdf/microdataframe.py,sha256=2lZU3FAtVCgKiVD-iD_3xu3NMEEl-7Tbn-T-aOR_ihc,33920
3
+ microdf/microseries.py,sha256=2-UmvJJkxycvqtIW6NfQr1HXFs-LTRctvQr6bkVNYdI,25061
4
+ microdf/tests/conftest.py,sha256=u-EMyX1-u_nM-YO0RJYCzYHQDXxUI2WQE6GkyJlErqg,150
5
+ microdf/tests/test_microseries_dataframe.py,sha256=YidEKYJwwPyCf_ZiAXoc8kydHj4XkZO-0jXQ-olouho,16284
6
+ microdf/tests/test_pandas3_compatibility.py,sha256=p4SZoW59REA5GV84HH9InfCdKQ1nEBGmatnRK84GiGY,8623
7
+ microdf_python-1.2.2.dist-info/licenses/LICENSE,sha256=uPs-ASYnzlldpf2z8jeRgQFeEH3FLhSuX0rw0OKWoDU,1067
8
+ microdf_python-1.2.2.dist-info/METADATA,sha256=o-2nZ_NkEuvOF-BgVG-3oCRr_3X5YdXg15utoUPCfdM,2469
9
+ microdf_python-1.2.2.dist-info/WHEEL,sha256=YCfwYGOYMi5Jhw2fU4yNgwErybb2IX5PEwBKV4ZbdBo,91
10
+ microdf_python-1.2.2.dist-info/top_level.txt,sha256=T2WFPTygQQMdS3GF8YpZ12DKfMGrspbZ3r7z-e3KfiM,8
11
+ microdf_python-1.2.2.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.10.1)
2
+ Generator: setuptools (82.0.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,11 +0,0 @@
1
- microdf/__init__.py,sha256=ldRvhE8t4cD7qlxQ5yLndMnWEUYpDw4m-jCDV_psXkY,319
2
- microdf/microdataframe.py,sha256=h0vIuCACMo1BuV3VKDIEfhc_UwMUV5kUsnlQe3bHfgM,33539
3
- microdf/microseries.py,sha256=YRnSHVm3mGGd1_-D29BAUDaqWoIiwGjJPKYUrnWbinY,23376
4
- microdf/tests/conftest.py,sha256=u-EMyX1-u_nM-YO0RJYCzYHQDXxUI2WQE6GkyJlErqg,150
5
- microdf/tests/test_microseries_dataframe.py,sha256=lG2_3lJqTdGekbbJRFl0Vp0b4DEQwTk6scXr-ncOHgs,14647
6
- microdf/tests/test_pandas3_compatibility.py,sha256=H2pRtYoLkQD3MEv1Xh6J38b4POaUae9mGRwsLhf1rng,7807
7
- microdf_python-1.2.0.dist-info/licenses/LICENSE,sha256=uPs-ASYnzlldpf2z8jeRgQFeEH3FLhSuX0rw0OKWoDU,1067
8
- microdf_python-1.2.0.dist-info/METADATA,sha256=uBlNPTndvTGm0pI69qD9O1vIgFfckqc-S7Oe0wZDdbo,2420
9
- microdf_python-1.2.0.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
10
- microdf_python-1.2.0.dist-info/top_level.txt,sha256=T2WFPTygQQMdS3GF8YpZ12DKfMGrspbZ3r7z-e3KfiM,8
11
- microdf_python-1.2.0.dist-info/RECORD,,