query: fix missing operator attribute on Query objects - #67
Merged
Conversation
thesamesam
approved these changes
Aug 28, 2026
thesamesam
left a comment
Member
There was a problem hiding this comment.
I look forward to when we can clean a lot of this up!
portage.dep.Atom now uses __slots__ and exposes operator as a read-only @Property backed by _operator, so it no longer appears in atom.__dict__. Query.__init__ copies atom.__dict__ into self but never picked up operator, same gap already patched here for cpv, _version, and _cp. Dependencies (a Query subclass) then lacked .operator entirely, crashing equery d with AttributeError when Atom.intersects() compared against it. Bug: https://bugs.gentoo.org/981521 Signed-off-by: Matt Turner <mattst88@gentoo.org>
Atom.intersects() type-checks its argument since portage removed str
subtyping from Atom, so it needs a real Atom object, not a Dependencies
(a Query subclass) or a plain string.
graph_reverse_depends() called dep.intersects(self) where self is a
Dependencies object. Pass self.atom instead, but that then exposed a
second bug: gentoolkit.atom.Atom.__init__ sets self.atom to the raw atom
string it was constructed from (used by __repr__/__str__).
Query.__init__ copied that string into self.atom via __dict__.update(),
and its fallback except branch set self.atom = self.cpv (also a plain
string), so Query.atom was never actually usable as an Atom. Fix both:
restore self.atom to the real Atom object in the success path, and
construct one from self.cpv in the fallback path.
That still leaves bare package-name queries (e.g. "simdjson") crashing:
they parse as neither a valid atom nor a valid CPV, so Query.__init__
falls back further to a plain string in self.atom, which
Atom.intersects() can't type-check. Since gentoolkit's Atom can't
represent a name-only atom at all (portage.dep.Atom rejects it),
graph_reverse_depends() now passes self instead of self.atom whenever
self.atom isn't a real Atom. self already carries the .cp/.category/.name
attributes intersects() needs for its name-only comparison, and since
self.cp (unslashed) never equals dep.cp ("cat/pkg"), that comparison
always takes the early-return branch, so the attributes intersects()
doesn't check (.repo, .slot, etc.) are never touched.
Bug: https://bugs.gentoo.org/981521
Signed-off-by: Matt Turner <mattst88@gentoo.org>
portage.dep.Atom.__new__ now interns instances in a module-level cache keyed only by the atom string and parse flags, not by the constructor's class. Constructing gentoolkit.atom.Atom with a string already interned elsewhere as a plain portage.dep.Atom silently returns that cached instance instead of one of our subclass, so methods we override (like intersects()) resolve to portage's implementation instead of ours. Reproduced with portage d52efac67: gentoolkit.atom.Atom() returned a plain portage.dep.Atom whenever the same atom string had already been interned by portage itself, which happens constantly in normal use. This also explains why equery d was under-reporting some reverse dependencies: portage.dep.Atom.intersects() and our own implementation don't always agree. Always calling object.__new__(cls) to bypass the cache broke CI, which pins portage 3.0.70: through 3.0.81.3, portage.dep.Atom subclasses str instead of using an intern cache, so object.__new__(cls) raised "TypeError: object.__new__(Atom) is not safe, use str.__new__()". Atom.__new__ now checks whether portage.dep.Atom is still a str subclass and, if so, allocates via str.__new__(cls, atom) instead; that version has no cache to bypass, so this is just correct allocation, not a workaround. Bug: https://bugs.gentoo.org/981521 Signed-off-by: Matt Turner <mattst88@gentoo.org>
thesamesam
approved these changes
Aug 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
portage.dep.Atom now uses
__slots__and exposes operator as a read-only@propertybacked by_operator, so it no longer appears inatom.__dict__.Query.__init__copiesatom.__dict__intoselfbut never picked upoperator, same gap already patched here forcpv,_version, and_cp.Dependencies(aQuerysubclass) then lacked.operatorentirely, crashingequery dwithAttributeErrorwhenAtom.intersects()compared against it.Bug: https://bugs.gentoo.org/981521