-
Notifications
You must be signed in to change notification settings - Fork 87
Explicit methods for "#e" and "#p" Filter
attrs; Filter
test suite
#33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Correct me if I'm misunderstanding, but I think these changes will break how we handle NIP-12 |
Ah, I see @jeffthibault. I didn't realize before that the expected usage was something like:
To me that requires too much direct knowledge of the Nostr spec (as evidenced by my own gaps here!). I had been trying:
Or something along those lines because I was expecting it to match the format of the I think for both
I'll rework this PR and see if I can strike the right balance. |
Filter
to match NIP-01 "#e" and "#p" attrsFilter
attrs; Filter
test suite
Updated. Preserved the explicit methods for 'e' and 'p' but added Breaking change: Bugfix in |
Ahh good catch on the event ID. I’m not sure how I missed that. Can we move the compute is line below setting the |
(I made a mess of my attempts to restore #24 in this branch. Fixed it all now and squashed those commits) |
Thanks @kdmukai, this is awesome! I think it makes sense to abstract away as much of the spec as possible and this PR does that. Here's one question I have, let's say I want to get events with the |
Will address other arbitrary tags like delegation. I think my filter match logic on tags is wrong. I got the
I'm iterating over a single Event 'p' tag when searching for the two pubkeys in my filter. I should be looking across all Working on a fix and more robust test cases that better reflect real-world |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't a critical change, but might help make the code more clear. I am trying to track down instances where mutable objects are used as default args as that seems to be causing unexpected behavior. Which lead me down a rabbit hole here...
It turns out to not be an issue for the Filters
argument initlist
because UserList
recreates the list object upon init. In the UserList
class the default initlist
is None
as opposed to []
. It might make sense to also default to None
in Filters
just to make this behavior clear.
Looks like the original code has two bugs.
from nostr.event import Event
from nostr.filter import Filter
event1 = Event(
public_key="somepubkey",
content="Anyone know what 2+2 = ?",
)
event2 = Event(
public_key="someotherpubkey",
content="It's 4!",
tags=[
['e', event1.id], # Replies reference which note they're directly responding to
['p', event1.public_key], # Replies reference who they're responding to
],
)
filter = Filter(
tags={'#p': [event1.public_key]}
)
assert filter.matches(event2) # fails due to 'e' tag
event2 = Event(
public_key="someotherpubkey",
content="It's 4!",
tags=[
['p', event1.public_key], # Replies reference who they're responding to
],
)
assert filter.matches(event2) # succeeds
event2 = Event(
public_key="someotherpubkey",
content="It's 4!",
tags=[
['p', event1.public_key], # Replies reference who they're responding to
['p', "some_other_pubkey"],
],
)
assert filter.matches(event2) # fails due to second 'p' tag |
Yup, thanks for the clear explanation. I'm not surprised there were bugs. I have always thought that handling the tags was kinda tricky. |
Updated! Tag filtering should now:
Tests updated with much better organization and much better readability. Ditched the |
Thanks @kdmukai! This is fantastic and fixes up the filter classes nicely. Tested ACK. |
Explicit methods for "#e" and "#p" tag filters
event_refs
: the "#e" attr; list of event ids referenced in an "e" tagpubkey_refs
: the "#p" attr; list of pubkeys referenced in a "p" tagRationale: users shouldn't have to know the protocol-level formatting details. Much more human-friendly to have explicit methods that describe exactly what the additional filter does.
Example usage
Preserves NIP-12 arbitrary single-letter tag filters
add_arbitrary_tag
will accept any single-letter tag and list of valuesPEP-8 compliance on
None
testsPEP-8 says that testing against
None
should useis
oris not
.Opinionated minor refactor
Filter.IDs
->Filter.event_ids
Tests for
Filter
andFilters
addedFairly thorough tests of the updated approach to 'e' and 'p' tag filters, plus overall basic usage.
Grouped relevant tests together into their own classes primarily for organizational purposes. Also allows you to run just that one class' tests:
Note: the "module"-level fixtures could really just be globals, but fixtures are widely preferred over globals. I don't love that the fixture approach added a little more repetitive boilerplate (including them as input args in every test method). But I opted to follow the best practice, even though I don't really see what it gained us here!
Further Work
Filter
be refactored into adataclass
(as I've done elsewhere); the unnecessary boilerplate in__init__
can be completely avoided since no real work is being done there.Filters
be renamed toFilterList
. It's more explicit and IMO more pythonic. Reduces (the admittedly minor) confusion with theFilter
class.