Closed dgw closed 8 months ago
Fix for
pop()
looks reasonable to me.
Fun fact: It wasn't reasonable, and in fact didn't raise KeyError
if the key is missing and no default
was provided.
Fixed that, and checked off some more of my task list w/fixes for .copy()
, del memory['KeY']
, and .get()
.
Still draft, though. I have several more behaviors to retest and then fix if necessary.
Think I'm about burned out on this for the day. But if my notes are correct, only __eq__()
/__ne__()
and setdefault()
are left to check/unit-test/maybe-fix. π
Turns out I lied about being done for the day. setdefault()
was a pretty simple one, and then after toying with __eq__()
for a bit I just decided not to bother.
Objects of different types probably should be considered unequal, unless there's a really good use-case I'm missing. (Anyone who really wants to force a comparison between a regular dict
and a SopelIdentifierMemory
can test identifier_memory == SopelIdentifierMemory(my_normal_dict)
instead, since this patch fixes that behavior.)
Aha, need to decide what to do about those "assert statement has a side effect" errors from CodeQL. Now that I eliminated the intermediate variables from those tests, I don't really want to put them back. π
Objects of different types probably should be considered unequal
In this case, absolutely, yes. A SopelIdentifierMemory is a very specific structure that has a very specific behavior. If people are going to do weird stuff with it, that weird stuff shouldn't work.
Welp, looks like no more CI builds on this branch until I rebase. Y'all mind if I squash out the fixups at the same time?
Yes go ahead, this will fix the conflict too.
this will fix the conflict too
Yep, that's why I wanted to rebase. Hard to continue bikeshedding new test cases if CI won't run any more. π
Ran 3.10 & 3.8 tests locally; pushing in a moment, once I review the final history for rebase mistakesβ¦ I wound up doing three passes on it so there'd be less chance of putting fixups in the wrong order by accident, and I'm still not quite positive that I put everything in the right order. π
Got carried away and used git rebase --exec
to run lint + tests on Python 3.11 for every commit in the cleaned-up history.
But because of that, I know every intermediate step works as expected and doesn't have any dangling imports or commits that were reordered incorrectly. :)
Edit: Why oh why did Python 3.8 linting fail? I specifically checked it before the whole --exec
thing under 3.11! π
Edit 2: Fixed, of course. My linter fixup commit must have gotten lost somewhere in the rebase. Comparison locally of the old HEAD (ae6c337c9b8da4c3ac59a0502f1eb2e789ed70ae) vs. current HEAD shows that no other changes slipped. I must have screwed up a conflict resolution and pasted the old MemoryConstructorInput
line on top of the fixed one.
I have another rebase in my future, apparently. Hopefully @SnoopJ can revisit the one or two open threads he started by the time Exi comes back from being "AFK" (as he said) for a few days, and I can rebase one last time with all the feedback/fixups then.
The fixups I just pushed (plus one technically unrelated new test I'm shoehorning in) catch even more edge cases that were missed, which @SnoopJ's nitpicks nudged me to find either directly or indirectly. Another very helpful review, thanks!
Latest force-push to squash out all the fixups moved one of the tests within the file, but meh. I made sure that the commit order is sane using git rebase master --exec '<pip3 deps> && <run lint/test>'
and all the intermediate stages pass. I verified each commit's diff manually to be even more sure that the intermediate steps make logical sense. Can't imagine what else I could double check at this point, so let's :shipit:
Note: if you really really want a nitpick at this point, I still don't think it's necessary to do any assertion about how a builtin dict works.
I reduced the number of those, if not completely eliminated them. You're right that it isn't worth delaying the patch any longer.
Description
Tin. Will resolve #2524.
Checklist
make qa
(runsmake lint
andmake test
)Notes
Started as a partial, untested fix from my tablet to reserve the PR number. New day, new task list:
del d['KeY']
d.clear()
(appears to work, but the object becomes a regulardict
and loses theIdentifier
magic)d.copy()
Made a copym
and added another item to it, verifying that the new item did not appear in the originald
. However, the new objectm
is adict
, not aSopelIdentifierMemory
.d.get('KeY')
Returns the default passed to.get()
, notkey
's value.d.pop('KeY')
(currently raisesKeyError
)d.pop('KeY', 'default')
(currently always returns'default'
)d.pop('NotInDict')
ReturnsNone
but should raiseKeyError
.d.setdefault('KeY', 'default')
With'key' in d
, returns'default'
& adds'KeY'
tod
as a regular string, notIdentifier
.d.update(a_plain_dict)
Ifd
hasIdentifier('thing1')
as a key, anda_plain_dict
has'ThinG1'
(a regular string), they will not be merged correctly andd
will now also have a regular string key called'ThinG1'
.d | a_plain_dict
Same problem asd.update(a_plain_dict)
.d |= a_plain_dict
Same problem asd.update(a_plain_dict)
andd | a_plain_dict
.[ ]Ifd == a_plain_dict
a_plain_dict
has the same key/value pairs but the key capitalization doesn't matchIdentifier
's canonical (lowercase) internal representation, the equality check returnsFalse
. Decided to NAK this one and let them be unequal. It's an easily reversible decision, since this just preserves the existing behavior (so there's no worry about plugin authors screaming that we keep changing the rules π).result = SopelIdentifierMemory({'KeY': 'foo'})
result
is of typeSopelIdentifierMemory
, but without the magic. Existing keys are not converted toIdentifier
, and'key' in result
doesn't work as expected for that type. In fact, even'KeY' in result
returnsFalse
for the example above, andresult['KeY'] raises
KeyError`. Even basic functionality of the resulting fake identifier memory is completely broken.