Ticket #153 (closed defect: fixed)
Opened 6 years ago
Last modified 6 years ago
Incompatible non-empty rpm.mi boolean value change in 4.8.0, len/count() issue
Reported by: scop Assigned to: pmatilai
Priority: major Milestone:
Component: rpm-python Version: RPM Development
Keywords: Cc:
Description
The following script demonstrates what I think are two problems with non-empty rpm.mi boolean value and len/count():
import rpm
ts = rpm.TransactionSet()
mi = ts.dbMatch()
mi.pattern("name", rpm.RPMMIRE_GLOB, "r*")
if mi:
print "mi true"
else:
print "mi false"
try:
print "len: %d" % len(mi)
except:
pass
print "count(): %d" % mi.count()
c = 0
for m in mi:
c += 1
print "real: %d" % c
With 4.4.2.3 on CentOS 5 I get:
mi true
count(): 0
real: 15
With 4.7.2 on Fedora 12 I get:
mi true
count(): 0
real: 37
With 4.8.0 on Fedora 13 I get:
mi false
len: 0
count(): 0
real: 25
Observations:
- The boolean value of non-empty mi changed incompatibly between 4.7.2 and 4.8.0 (breaks for example installed package globbing in rpmlint)
- I think both mi.count() and len(mi) are (and have been) somehow broken in this case, they should return the same number as the "real" IMO but return 0
On the other hand, mi's returned from for example
ts.dbMatch("name", "rpm")
behave like I'd expect in all these
versions, both truth value and len/count() wise.
Change History
03/20/10 10:42:46 changed by pmatilai
Hmm, the behavior change here is not intentional, I'll need to check where that comes from. The python bindings saw quite a churn between 4.7.x and 4.8.x so, its more surprising that there has been so few (reported) breakages than the other way around :)
The iterator count has always been rather broken (on C-level too): it only works on exact matches against index tags. Eg:
mi = ts.dbMatch('name') mi.count()
0
mi = ts.dbMatch('name', 'kernel') mi.count()
3
03/20/10 11:39:54 changed by pmatilai
- owner changed from RpmTickets to pmatilai.
- status changed from new to assigned.
Right... this is the cause: http://docs.python.org/library/stdtypes.html#truth-value-testing
instances of user-defined classes, if the class defines a nonzero() or len() method, when that method returns the integer zero or bool value False.
Now that the iterator implements __len__()
, that's what gets used for
truth value whereas any mi instance previously always returned True,
just like "foo = object()" evals to True. Reverting to former behavior
is easily achieved by adding __nonzero__()
which always returns True,
which is probably the less surprising behavior, considering how unusable
the __len__()
method is due to its unreliability.
03/21/10 20:46:49 changed by scop
Thanks for looking into this. Let me know if you find a "fix" and intend to ship it for Fedora 13 - I have a trivial fix for this already in rpmlint svn but won't bother shipping an update for this purpose if you intend to push a rpm update.
03/24/10 08:20:29 changed by pmatilai
- status changed from assigned to closed.
- resolution set to fixed.
Okay, fixed now: https://rpm.org/gitweb?p=rpm.git;a=commitdiff;h=40f788a7bf3741f9c613ff302d4e1b0ceec2658c
This is not actually 100% identical behavior to pre-4.8.0 which returned True no matter what, whereas now the truth value actually sorta means something (you get False when it knows there are no matches at all)
On the Fedora-side of things: fixed now in rawhide and will pull to F13 in near future, there are a few other fixes pending for 13 too.