patchdiff 0.3.8__py3-none-any.whl → 0.3.9__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.
patchdiff/produce.py CHANGED
@@ -98,6 +98,9 @@ class PatchRecorder:
98
98
  class DictProxy:
99
99
  """Proxy for dict objects that tracks mutations and generates patches."""
100
100
 
101
+ __slots__ = ("_data", "_path", "_proxies", "_recorder")
102
+ __hash__ = None # dicts are unhashable
103
+
101
104
  def __init__(self, data: Dict, recorder: PatchRecorder, path: Pointer):
102
105
  self._data = data
103
106
  self._recorder = recorder
@@ -217,6 +220,21 @@ class DictProxy:
217
220
  del self._proxies[key]
218
221
  return key, value
219
222
 
223
+ def values(self):
224
+ """Return proxied values so nested mutations are tracked."""
225
+ for key in self._data:
226
+ yield self._wrap(key, self._data[key])
227
+
228
+ def items(self):
229
+ """Return (key, proxied_value) pairs so nested mutations are tracked."""
230
+ for key in self._data:
231
+ yield key, self._wrap(key, self._data[key])
232
+
233
+ def __ior__(self, other):
234
+ """Implement |= operator (merge update)."""
235
+ self.update(other)
236
+ return self
237
+
220
238
 
221
239
  # Add simple reader methods to DictProxy
222
240
  _add_reader_methods(
@@ -226,18 +244,32 @@ _add_reader_methods(
226
244
  "__contains__",
227
245
  "__repr__",
228
246
  "__iter__",
247
+ # __reversed__ returns keys (not values), so pass-through is fine
229
248
  "__reversed__",
230
249
  "keys",
231
- "values",
232
- "items",
250
+ # values() and items() are implemented as custom methods above
251
+ # to return proxied nested objects
233
252
  "copy",
253
+ "__str__",
254
+ "__format__",
255
+ "__eq__",
256
+ "__ne__",
257
+ "__or__",
258
+ "__ror__",
234
259
  ],
235
260
  )
261
+ # Skipped dict methods:
262
+ # - fromkeys: classmethod, not relevant for proxy instances
263
+ # - __class_getitem__: typing support (dict[str, int]), not relevant for instances
264
+ # - __lt__, __le__, __gt__, __ge__: dicts don't support ordering comparisons
236
265
 
237
266
 
238
267
  class ListProxy:
239
268
  """Proxy for list objects that tracks mutations and generates patches."""
240
269
 
270
+ __slots__ = ("_data", "_path", "_proxies", "_recorder")
271
+ __hash__ = None # lists are unhashable
272
+
241
273
  def __init__(self, data: List, recorder: PatchRecorder, path: Pointer):
242
274
  self._data = data
243
275
  self._recorder = recorder
@@ -466,6 +498,31 @@ class ListProxy:
466
498
  # Invalidate all proxy caches as positions changed
467
499
  self._proxies.clear()
468
500
 
501
+ def __iter__(self):
502
+ """Iterate over list elements, wrapping nested structures in proxies."""
503
+ for i in range(len(self._data)):
504
+ yield self._wrap(i, self._data[i])
505
+
506
+ def __reversed__(self):
507
+ """Iterate in reverse, wrapping nested structures in proxies."""
508
+ for i in range(len(self._data) - 1, -1, -1):
509
+ yield self._wrap(i, self._data[i])
510
+
511
+ def __iadd__(self, other):
512
+ """Implement += operator (in-place extend)."""
513
+ self.extend(other)
514
+ return self
515
+
516
+ def __imul__(self, n):
517
+ """Implement *= operator (in-place repeat)."""
518
+ if n <= 0:
519
+ self.clear()
520
+ elif n > 1:
521
+ original = list(self._data)
522
+ for _ in range(n - 1):
523
+ self.extend(original)
524
+ return self
525
+
469
526
 
470
527
  # Add simple reader methods to ListProxy
471
528
  _add_reader_methods(
@@ -474,18 +531,34 @@ _add_reader_methods(
474
531
  "__len__",
475
532
  "__contains__",
476
533
  "__repr__",
477
- "__iter__",
478
- "__reversed__",
534
+ # __iter__ and __reversed__ are implemented as custom methods above
535
+ # to return proxied nested objects
479
536
  "index",
480
537
  "count",
481
538
  "copy",
539
+ "__str__",
540
+ "__format__",
541
+ "__eq__",
542
+ "__ne__",
543
+ "__lt__",
544
+ "__le__",
545
+ "__gt__",
546
+ "__ge__",
547
+ "__add__",
548
+ "__mul__",
549
+ "__rmul__",
482
550
  ],
483
551
  )
552
+ # Skipped list methods:
553
+ # - __class_getitem__: typing support (list[int]), not relevant for instances
484
554
 
485
555
 
486
556
  class SetProxy:
487
557
  """Proxy for set objects that tracks mutations and generates patches."""
488
558
 
559
+ __slots__ = ("_data", "_path", "_recorder")
560
+ __hash__ = None # sets are unhashable
561
+
489
562
  def __init__(self, data: Set, recorder: PatchRecorder, path: Pointer):
490
563
  self._data = data
491
564
  self._recorder = recorder
@@ -564,6 +637,31 @@ class SetProxy:
564
637
  self.add(value)
565
638
  return self
566
639
 
640
+ def difference_update(self, *others):
641
+ """Remove all elements found in others."""
642
+ for other in others:
643
+ for value in other:
644
+ if value in self._data:
645
+ self.remove(value)
646
+
647
+ def intersection_update(self, *others):
648
+ """Keep only elements found in all others."""
649
+ # Compute the intersection first, then remove what's not in it
650
+ keep = self._data.copy()
651
+ for other in others:
652
+ keep &= set(other)
653
+ values_to_remove = [v for v in self._data if v not in keep]
654
+ for value in values_to_remove:
655
+ self.remove(value)
656
+
657
+ def symmetric_difference_update(self, other):
658
+ """Update with symmetric difference."""
659
+ for value in other:
660
+ if value in self._data:
661
+ self.remove(value)
662
+ else:
663
+ self.add(value)
664
+
567
665
 
568
666
  # Add simple reader methods to SetProxy
569
667
  _add_reader_methods(
@@ -581,8 +679,26 @@ _add_reader_methods(
581
679
  "issubset",
582
680
  "issuperset",
583
681
  "copy",
682
+ "__str__",
683
+ "__format__",
684
+ "__eq__",
685
+ "__ne__",
686
+ "__le__",
687
+ "__lt__",
688
+ "__ge__",
689
+ "__gt__",
690
+ "__or__",
691
+ "__ror__",
692
+ "__and__",
693
+ "__rand__",
694
+ "__sub__",
695
+ "__rsub__",
696
+ "__xor__",
697
+ "__rxor__",
584
698
  ],
585
699
  )
700
+ # Skipped set methods:
701
+ # - __class_getitem__: typing support (set[int]), not relevant for instances
586
702
 
587
703
 
588
704
  def produce(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: patchdiff
3
- Version: 0.3.8
3
+ Version: 0.3.9
4
4
  Summary: MIT
5
5
  Project-URL: Homepage, https://github.com/fork-tongue/patchdiff
6
6
  Author-email: Korijn van Golen <korijn@gmail.com>, Berend Klein Haneveld <berendkleinhaneveld@gmail.com>
@@ -2,9 +2,9 @@ patchdiff/__init__.py,sha256=15flrOoL84AMf5VVQr1PVunxuZNLeRTfClXzJJgFOx0,192
2
2
  patchdiff/apply.py,sha256=zxjJ4sCivcy4WOZulQGfv2iduVeY0xnjlvZJkHIZhtY,1405
3
3
  patchdiff/diff.py,sha256=-Aj-8NGE1HRoLxVYNK1dFofACaY3fCCsIJo6ypkrl5U,6827
4
4
  patchdiff/pointer.py,sha256=2h5pWNin_TUhfDaib4UpYvuUBFT4WXAOmytYO0qsFWU,1777
5
- patchdiff/produce.py,sha256=SamyDqbCAXC_6heSCmL-jMKLt1kWzBIrGaSMBlc3q8g,24318
5
+ patchdiff/produce.py,sha256=cptJq6Lz2rKY-pjZ1MAgymmLWG16Qo08HqmoSnwpyMM,28105
6
6
  patchdiff/serialize.py,sha256=N0S9e0P49TBMb7ghM--h13MsF59ybiscjZ_auAErTq8,295
7
7
  patchdiff/types.py,sha256=BVKXOl3tnQOOml3VI_epTrLn79agi6sD5vNr2acC-yE,77
8
- patchdiff-0.3.8.dist-info/METADATA,sha256=cKrY_-pLivR7Rpg3pGQC1i8LbQSFONtTHbdK5rXJ8-o,3130
9
- patchdiff-0.3.8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
10
- patchdiff-0.3.8.dist-info/RECORD,,
8
+ patchdiff-0.3.9.dist-info/METADATA,sha256=xwBHulHd698IYfIZ2Q-8-1z1AHuIALYwElHm_QwWRAs,3130
9
+ patchdiff-0.3.9.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
10
+ patchdiff-0.3.9.dist-info/RECORD,,