scripts: Removed item/iter magic methods from fs object classes

So no more __getitem__, __contains__, or __iter__ for Rbyd, Btree, Mdir,
Mtree, Lfs.File, etc.

These were way too error-prone, especially when accidental unpacking
triggered unintended disk traversal and weird error states. We didn't
even use the implicit behavior because we preferred the full name for
heavy disk operations.

The motivation for this was Python not catching this bug, which is a bit
silly:

  rid, rattr, *path_ = rbyd
This commit is contained in:
Christopher Haster
2025-04-07 02:46:54 -05:00
parent 81b1a3cb71
commit b2911fbbe7
6 changed files with 1 additions and 304 deletions
-66
View File
@@ -900,18 +900,6 @@ class Rbyd:
else: else:
return rattr_ return rattr_
def __getitem__(self, key):
if not isinstance(key, tuple):
key = (key,)
return self.lookup(*key)
def __contains__(self, key):
if not isinstance(key, tuple):
key = (key,)
return self.lookup(*key) is not None
def rids(self, *, def rids(self, *,
path=False): path=False):
rid = -1 rid = -1
@@ -978,9 +966,6 @@ class Rbyd:
yield rattr_ yield rattr_
tag_ = rattr_.tag tag_ = rattr_.tag
def __iter__(self):
return self.rattrs()
# lookup by name # lookup by name
def namelookup(self, did, name): def namelookup(self, did, name):
# binary search # binary search
@@ -1185,18 +1170,6 @@ class Btree:
else: else:
return rattr_ return rattr_
def __getitem__(self, key):
if not isinstance(key, tuple):
key = (key,)
return self.lookup(*key)
def __contains__(self, key):
if not isinstance(key, tuple):
key = (key,)
return self.lookup(*key) is not None
# note leaves only iterates over leaf rbyds, whereas traverse # note leaves only iterates over leaf rbyds, whereas traverse
# traverses all rbyds # traverses all rbyds
def leaves(self, *, def leaves(self, *,
@@ -1327,9 +1300,6 @@ class Btree:
else: else:
yield rattr yield rattr
def __iter__(self):
return self.rattrs()
# lookup by name # lookup by name
def namelookupleaf(self, did, name, *, def namelookupleaf(self, did, name, *,
path=False, path=False,
@@ -1581,18 +1551,6 @@ class Mdir:
return self.rbyd.lookup(mid.mrid, tag, mask, return self.rbyd.lookup(mid.mrid, tag, mask,
path=path) path=path)
def __getitem__(self, key):
if not isinstance(key, tuple):
key = (key,)
return self.lookup(*key)
def __contains__(self, key):
if not isinstance(key, tuple):
key = (key,)
return self.lookup(*key) is not None
def mids(self, *, def mids(self, *,
path=False): path=False):
for r in self.rbyd.rids( for r in self.rbyd.rids(
@@ -1629,9 +1587,6 @@ class Mdir:
yield from self.rbyd.rattrs(mid.mrid, tag, mask, yield from self.rbyd.rattrs(mid.mrid, tag, mask,
path=path) path=path)
def __iter__(self):
return self.rattrs()
# lookup by name # lookup by name
def namelookup(self, did, name): def namelookup(self, did, name):
# unlike rbyd namelookup, we need an exact match here # unlike rbyd namelookup, we need an exact match here
@@ -1929,18 +1884,6 @@ class Mtree:
else: else:
return mdir, name return mdir, name
def __getitem__(self, key):
if not isinstance(key, tuple):
key = (key,)
return self.lookup(*key)
def __contains__(self, key):
if not isinstance(key, tuple):
key = (key,)
return self.lookup(*key) is not None
# iterate over all mdirs, this includes the mrootchain # iterate over all mdirs, this includes the mrootchain
def _leaves(self, *, def _leaves(self, *,
path=False, path=False,
@@ -2172,9 +2115,6 @@ class Mtree:
else: else:
yield rattr yield rattr
def __iter__(self):
return self.mids()
# lookup by name # lookup by name
def _namelookupleaf(self, did, name, *, def _namelookupleaf(self, did, name, *,
path=False, path=False,
@@ -3156,9 +3096,6 @@ class Lfs:
break break
mid = self.mid(mbid, mrid) mid = self.mid(mbid, mrid)
def __iter__(self):
return self.files()
def orphans(self, def orphans(self,
all=False): all=False):
all_ = all; del all all_ = all; del all
@@ -3536,9 +3473,6 @@ class Lfs:
path=path, path=path,
depth=depth) depth=depth)
def __iter__(self):
return self.datas()
# some convience operations for reading data # some convience operations for reading data
def bytes(self, *, def bytes(self, *,
depth=None): depth=None):
-66
View File
@@ -929,18 +929,6 @@ class Rbyd:
else: else:
return rattr_ return rattr_
def __getitem__(self, key):
if not isinstance(key, tuple):
key = (key,)
return self.lookup(*key)
def __contains__(self, key):
if not isinstance(key, tuple):
key = (key,)
return self.lookup(*key) is not None
def rids(self, *, def rids(self, *,
path=False): path=False):
rid = -1 rid = -1
@@ -1007,9 +995,6 @@ class Rbyd:
yield rattr_ yield rattr_
tag_ = rattr_.tag tag_ = rattr_.tag
def __iter__(self):
return self.rattrs()
# lookup by name # lookup by name
def namelookup(self, did, name): def namelookup(self, did, name):
# binary search # binary search
@@ -1214,18 +1199,6 @@ class Btree:
else: else:
return rattr_ return rattr_
def __getitem__(self, key):
if not isinstance(key, tuple):
key = (key,)
return self.lookup(*key)
def __contains__(self, key):
if not isinstance(key, tuple):
key = (key,)
return self.lookup(*key) is not None
# note leaves only iterates over leaf rbyds, whereas traverse # note leaves only iterates over leaf rbyds, whereas traverse
# traverses all rbyds # traverses all rbyds
def leaves(self, *, def leaves(self, *,
@@ -1356,9 +1329,6 @@ class Btree:
else: else:
yield rattr yield rattr
def __iter__(self):
return self.rattrs()
# lookup by name # lookup by name
def namelookupleaf(self, did, name, *, def namelookupleaf(self, did, name, *,
path=False, path=False,
@@ -1610,18 +1580,6 @@ class Mdir:
return self.rbyd.lookup(mid.mrid, tag, mask, return self.rbyd.lookup(mid.mrid, tag, mask,
path=path) path=path)
def __getitem__(self, key):
if not isinstance(key, tuple):
key = (key,)
return self.lookup(*key)
def __contains__(self, key):
if not isinstance(key, tuple):
key = (key,)
return self.lookup(*key) is not None
def mids(self, *, def mids(self, *,
path=False): path=False):
for r in self.rbyd.rids( for r in self.rbyd.rids(
@@ -1658,9 +1616,6 @@ class Mdir:
yield from self.rbyd.rattrs(mid.mrid, tag, mask, yield from self.rbyd.rattrs(mid.mrid, tag, mask,
path=path) path=path)
def __iter__(self):
return self.rattrs()
# lookup by name # lookup by name
def namelookup(self, did, name): def namelookup(self, did, name):
# unlike rbyd namelookup, we need an exact match here # unlike rbyd namelookup, we need an exact match here
@@ -1958,18 +1913,6 @@ class Mtree:
else: else:
return mdir, name return mdir, name
def __getitem__(self, key):
if not isinstance(key, tuple):
key = (key,)
return self.lookup(*key)
def __contains__(self, key):
if not isinstance(key, tuple):
key = (key,)
return self.lookup(*key) is not None
# iterate over all mdirs, this includes the mrootchain # iterate over all mdirs, this includes the mrootchain
def _leaves(self, *, def _leaves(self, *,
path=False, path=False,
@@ -2201,9 +2144,6 @@ class Mtree:
else: else:
yield rattr yield rattr
def __iter__(self):
return self.mids()
# lookup by name # lookup by name
def _namelookupleaf(self, did, name, *, def _namelookupleaf(self, did, name, *,
path=False, path=False,
@@ -3185,9 +3125,6 @@ class Lfs:
break break
mid = self.mid(mbid, mrid) mid = self.mid(mbid, mrid)
def __iter__(self):
return self.files()
def orphans(self, def orphans(self,
all=False): all=False):
all_ = all; del all all_ = all; del all
@@ -3565,9 +3502,6 @@ class Lfs:
path=path, path=path,
depth=depth) depth=depth)
def __iter__(self):
return self.datas()
# some convience operations for reading data # some convience operations for reading data
def bytes(self, *, def bytes(self, *,
depth=None): depth=None):
-30
View File
@@ -808,18 +808,6 @@ class Rbyd:
else: else:
return rattr_ return rattr_
def __getitem__(self, key):
if not isinstance(key, tuple):
key = (key,)
return self.lookup(*key)
def __contains__(self, key):
if not isinstance(key, tuple):
key = (key,)
return self.lookup(*key) is not None
def rids(self, *, def rids(self, *,
path=False): path=False):
rid = -1 rid = -1
@@ -886,9 +874,6 @@ class Rbyd:
yield rattr_ yield rattr_
tag_ = rattr_.tag tag_ = rattr_.tag
def __iter__(self):
return self.rattrs()
# lookup by name # lookup by name
def namelookup(self, did, name): def namelookup(self, did, name):
# binary search # binary search
@@ -1093,18 +1078,6 @@ class Btree:
else: else:
return rattr_ return rattr_
def __getitem__(self, key):
if not isinstance(key, tuple):
key = (key,)
return self.lookup(*key)
def __contains__(self, key):
if not isinstance(key, tuple):
key = (key,)
return self.lookup(*key) is not None
# note leaves only iterates over leaf rbyds, whereas traverse # note leaves only iterates over leaf rbyds, whereas traverse
# traverses all rbyds # traverses all rbyds
def leaves(self, *, def leaves(self, *,
@@ -1235,9 +1208,6 @@ class Btree:
else: else:
yield rattr yield rattr
def __iter__(self):
return self.rattrs()
# lookup by name # lookup by name
def namelookupleaf(self, did, name, *, def namelookupleaf(self, did, name, *,
path=False, path=False,
-66
View File
@@ -857,18 +857,6 @@ class Rbyd:
else: else:
return rattr_ return rattr_
def __getitem__(self, key):
if not isinstance(key, tuple):
key = (key,)
return self.lookup(*key)
def __contains__(self, key):
if not isinstance(key, tuple):
key = (key,)
return self.lookup(*key) is not None
def rids(self, *, def rids(self, *,
path=False): path=False):
rid = -1 rid = -1
@@ -935,9 +923,6 @@ class Rbyd:
yield rattr_ yield rattr_
tag_ = rattr_.tag tag_ = rattr_.tag
def __iter__(self):
return self.rattrs()
# lookup by name # lookup by name
def namelookup(self, did, name): def namelookup(self, did, name):
# binary search # binary search
@@ -1142,18 +1127,6 @@ class Btree:
else: else:
return rattr_ return rattr_
def __getitem__(self, key):
if not isinstance(key, tuple):
key = (key,)
return self.lookup(*key)
def __contains__(self, key):
if not isinstance(key, tuple):
key = (key,)
return self.lookup(*key) is not None
# note leaves only iterates over leaf rbyds, whereas traverse # note leaves only iterates over leaf rbyds, whereas traverse
# traverses all rbyds # traverses all rbyds
def leaves(self, *, def leaves(self, *,
@@ -1284,9 +1257,6 @@ class Btree:
else: else:
yield rattr yield rattr
def __iter__(self):
return self.rattrs()
# lookup by name # lookup by name
def namelookupleaf(self, did, name, *, def namelookupleaf(self, did, name, *,
path=False, path=False,
@@ -1538,18 +1508,6 @@ class Mdir:
return self.rbyd.lookup(mid.mrid, tag, mask, return self.rbyd.lookup(mid.mrid, tag, mask,
path=path) path=path)
def __getitem__(self, key):
if not isinstance(key, tuple):
key = (key,)
return self.lookup(*key)
def __contains__(self, key):
if not isinstance(key, tuple):
key = (key,)
return self.lookup(*key) is not None
def mids(self, *, def mids(self, *,
path=False): path=False):
for r in self.rbyd.rids( for r in self.rbyd.rids(
@@ -1586,9 +1544,6 @@ class Mdir:
yield from self.rbyd.rattrs(mid.mrid, tag, mask, yield from self.rbyd.rattrs(mid.mrid, tag, mask,
path=path) path=path)
def __iter__(self):
return self.rattrs()
# lookup by name # lookup by name
def namelookup(self, did, name): def namelookup(self, did, name):
# unlike rbyd namelookup, we need an exact match here # unlike rbyd namelookup, we need an exact match here
@@ -1886,18 +1841,6 @@ class Mtree:
else: else:
return mdir, name return mdir, name
def __getitem__(self, key):
if not isinstance(key, tuple):
key = (key,)
return self.lookup(*key)
def __contains__(self, key):
if not isinstance(key, tuple):
key = (key,)
return self.lookup(*key) is not None
# iterate over all mdirs, this includes the mrootchain # iterate over all mdirs, this includes the mrootchain
def _leaves(self, *, def _leaves(self, *,
path=False, path=False,
@@ -2129,9 +2072,6 @@ class Mtree:
else: else:
yield rattr yield rattr
def __iter__(self):
return self.mids()
# lookup by name # lookup by name
def _namelookupleaf(self, did, name, *, def _namelookupleaf(self, did, name, *,
path=False, path=False,
@@ -3113,9 +3053,6 @@ class Lfs:
break break
mid = self.mid(mbid, mrid) mid = self.mid(mbid, mrid)
def __iter__(self):
return self.files()
def orphans(self, def orphans(self,
all=False): all=False):
all_ = all; del all all_ = all; del all
@@ -3493,9 +3430,6 @@ class Lfs:
path=path, path=path,
depth=depth) depth=depth)
def __iter__(self):
return self.datas()
# some convience operations for reading data # some convience operations for reading data
def bytes(self, *, def bytes(self, *,
depth=None): depth=None):
-60
View File
@@ -823,18 +823,6 @@ class Rbyd:
else: else:
return rattr_ return rattr_
def __getitem__(self, key):
if not isinstance(key, tuple):
key = (key,)
return self.lookup(*key)
def __contains__(self, key):
if not isinstance(key, tuple):
key = (key,)
return self.lookup(*key) is not None
def rids(self, *, def rids(self, *,
path=False): path=False):
rid = -1 rid = -1
@@ -901,9 +889,6 @@ class Rbyd:
yield rattr_ yield rattr_
tag_ = rattr_.tag tag_ = rattr_.tag
def __iter__(self):
return self.rattrs()
# lookup by name # lookup by name
def namelookup(self, did, name): def namelookup(self, did, name):
# binary search # binary search
@@ -1108,18 +1093,6 @@ class Btree:
else: else:
return rattr_ return rattr_
def __getitem__(self, key):
if not isinstance(key, tuple):
key = (key,)
return self.lookup(*key)
def __contains__(self, key):
if not isinstance(key, tuple):
key = (key,)
return self.lookup(*key) is not None
# note leaves only iterates over leaf rbyds, whereas traverse # note leaves only iterates over leaf rbyds, whereas traverse
# traverses all rbyds # traverses all rbyds
def leaves(self, *, def leaves(self, *,
@@ -1250,9 +1223,6 @@ class Btree:
else: else:
yield rattr yield rattr
def __iter__(self):
return self.rattrs()
# lookup by name # lookup by name
def namelookupleaf(self, did, name, *, def namelookupleaf(self, did, name, *,
path=False, path=False,
@@ -1504,18 +1474,6 @@ class Mdir:
return self.rbyd.lookup(mid.mrid, tag, mask, return self.rbyd.lookup(mid.mrid, tag, mask,
path=path) path=path)
def __getitem__(self, key):
if not isinstance(key, tuple):
key = (key,)
return self.lookup(*key)
def __contains__(self, key):
if not isinstance(key, tuple):
key = (key,)
return self.lookup(*key) is not None
def mids(self, *, def mids(self, *,
path=False): path=False):
for r in self.rbyd.rids( for r in self.rbyd.rids(
@@ -1552,9 +1510,6 @@ class Mdir:
yield from self.rbyd.rattrs(mid.mrid, tag, mask, yield from self.rbyd.rattrs(mid.mrid, tag, mask,
path=path) path=path)
def __iter__(self):
return self.rattrs()
# lookup by name # lookup by name
def namelookup(self, did, name): def namelookup(self, did, name):
# unlike rbyd namelookup, we need an exact match here # unlike rbyd namelookup, we need an exact match here
@@ -1852,18 +1807,6 @@ class Mtree:
else: else:
return mdir, name return mdir, name
def __getitem__(self, key):
if not isinstance(key, tuple):
key = (key,)
return self.lookup(*key)
def __contains__(self, key):
if not isinstance(key, tuple):
key = (key,)
return self.lookup(*key) is not None
# iterate over all mdirs, this includes the mrootchain # iterate over all mdirs, this includes the mrootchain
def _leaves(self, *, def _leaves(self, *,
path=False, path=False,
@@ -2095,9 +2038,6 @@ class Mtree:
else: else:
yield rattr yield rattr
def __iter__(self):
return self.mids()
# lookup by name # lookup by name
def _namelookupleaf(self, did, name, *, def _namelookupleaf(self, did, name, *,
path=False, path=False,
+1 -16
View File
@@ -791,18 +791,6 @@ class Rbyd:
else: else:
return rattr_ return rattr_
def __getitem__(self, key):
if not isinstance(key, tuple):
key = (key,)
return self.lookup(*key)
def __contains__(self, key):
if not isinstance(key, tuple):
key = (key,)
return self.lookup(*key) is not None
def rids(self, *, def rids(self, *,
path=False): path=False):
rid = -1 rid = -1
@@ -869,9 +857,6 @@ class Rbyd:
yield rattr_ yield rattr_
tag_ = rattr_.tag tag_ = rattr_.tag
def __iter__(self):
return self.rattrs()
# lookup by name # lookup by name
def namelookup(self, did, name): def namelookup(self, did, name):
# binary search # binary search
@@ -1647,7 +1632,7 @@ def dbg_tree(rbyd, *,
# dynamically size the id field # dynamically size the id field
w_width = mt.ceil(mt.log10(max(1, rbyd.weight)+1)) w_width = mt.ceil(mt.log10(max(1, rbyd.weight)+1))
for i, (rid, rattr) in enumerate(rbyd): for i, (rid, rattr) in enumerate(rbyd.rattrs()):
# show human-readable tag representation # show human-readable tag representation
print('%08x: %s%*s %-*s %s' % ( print('%08x: %s%*s %-*s %s' % (
rattr.toff, rattr.toff,