Skip to content
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

Add Weblate Fedora Messaging schema #364

Merged

Conversation

harriebird
Copy link
Contributor

Proposed changes

This adds a new schema for Weblate Fedora Messaging.
This solves issue fedora_messaging#268.

Checklist

  • Lint and unit tests pass locally with my changes.
  • I have added tests that prove my fix is effective or that my feature works.
  • I have added documentation to describe my feature.
  • I have squashed my commits into logic units.
  • I have described the changes in the commit messages.

Other information

Copy link

codecov bot commented Oct 8, 2024

Codecov Report

Attention: Patch coverage is 97.72727% with 3 lines in your changes missing coverage. Please review.

Project coverage is 98.25%. Comparing base (45163d1) to head (1c76d96).
Report is 108 commits behind head on main.

Files with missing lines Patch % Lines
weblate_schemas/messages.py 95.31% 3 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##              main     #364      +/-   ##
===========================================
- Coverage   100.00%   98.25%   -1.75%     
===========================================
  Files            3        5       +2     
  Lines           43      172     +129     
===========================================
+ Hits            43      169     +126     
- Misses           0        3       +3     
Flag Coverage Δ
unittests 98.25% <97.72%> (-1.75%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@nijel
Copy link
Member

nijel commented Oct 8, 2024

Looks good for the body schema, now we need to wrap it in Python classes (see https://fedora-messaging.readthedocs.io/en/stable/user-guide/messages.html). Maybe header schema will be needed as well (I didn't investigate that).

Copy link
Member

@nijel nijel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add some kind of testing that the message classes work on the expected payload?

return "https://weblate.org/static/weblate-128.png"


class WeblateMessage(BaseMessage):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably should include versioning to allow future changes:

Suggested change
class WeblateMessage(BaseMessage):
class WeblateV1Message(BaseMessage):

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need to have it for the initial message schema, but will need that for any updated message schema. The first one could be WeblateMessage, but the changed one would need to be WeblateV2Message. Still a good idea to have the versioning in from start.

Keep in mind that you only need to do that if you are removing something from the message schema, adding things doesn't break anything.

"""Initialize the WeblateMessage class with loading of the body_schema."""
super().__init__(**kwargs)
self.body_schema = load_schema("weblate-messaging.schema.json")

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least summary should also be present, based on https://pagure.io/fedora-infrastructure/issue/8291#comment-857387.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also recommend to add properties that are used by FMN as usernames and packages. See https://fedora-messaging.readthedocs.io/en/stable/user-guide/messages.html#example-schema

Also each Fedora application should have app_name property.

Copy link

@Zlopez Zlopez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Few comments for the schema

return "https://weblate.org/static/weblate-128.png"


class WeblateMessage(BaseMessage):
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need to have it for the initial message schema, but will need that for any updated message schema. The first one could be WeblateMessage, but the changed one would need to be WeblateV2Message. Still a good idea to have the versioning in from start.

Keep in mind that you only need to do that if you are removing something from the message schema, adding things doesn't break anything.

"""Initialize the WeblateMessage class with loading of the body_schema."""
super().__init__(**kwargs)
self.body_schema = load_schema("weblate-messaging.schema.json")

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also recommend to add properties that are used by FMN as usernames and packages. See https://fedora-messaging.readthedocs.io/en/stable/user-guide/messages.html#example-schema

Also each Fedora application should have app_name property.

@harriebird harriebird force-pushed the feature/add-weblate-fedora-messaging-schema branch from f045c55 to 5b03512 Compare October 13, 2024 10:12
@harriebird
Copy link
Contributor Author

Hi everyone, thank you for your comments. The latest commit contains the following changes:

  • Renamed the message class to WeblateV1Message
  • Added properties summary and usernames into the WeblateV1Message class
  • Added entry point
  • Replaced jsonschema with jsonschema[format] to extend format validation support
  • Added new tests

requirements.txt Outdated
@@ -1,4 +1,5 @@
fedora-messaging
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be an optional dependency, there is no need to require it for somebody wanting other schemas.

requirements.txt Outdated
fqdn
jsonschema
jsonschema[format]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps this belongs to requirements-test.txt?

setup.py Outdated
@@ -11,4 +11,13 @@
with open("requirements.txt") as handle:
REQUIRES = list(handle.read().splitlines())

setup(install_requires=REQUIRES)
setup(
name="weblate_schemas",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already present in setup.cfg.

setup.py Outdated
"base.message=weblate_schemas.messages:BaseMessage",
"weblate.message=weblate_schemas.messages:WeblateV1Message",
]
},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should go to setup.cfg.

setup.py Outdated
name="weblate_schemas",
entry_points={
"fedora.messages": [
"base.message=weblate_schemas.messages:BaseMessage",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please prefix the key here with weblate.. The base.message key is already used by Fedora Messaging

setup.py Outdated
entry_points={
"fedora.messages": [
"base.message=weblate_schemas.messages:BaseMessage",
"weblate.message=weblate_schemas.messages:WeblateV1Message",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recommend suffixing this key with .v1, as it is the version 1 of the schema.


def __init__(self, **kwargs) -> None:
"""Initialize BaseMessage class."""
super().__init__(**kwargs)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This block is not necessary, no need to redefine __init__ if you're just calling the superclass.

return self.body["user"]

@property
def id(self) -> int:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The id property is reserved by Fedora Messaging. You can use something like change_id if you want.

def usernames(self):
"""Return the usernames involved."""
users = {self.body["author"], self.body["user"]}
return list(users)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would make testing easier if the list is sorted alphabetically, but this is just a non-blocking suggestion.


def __str__(self) -> str:
"""Return a human-readable representation of the message."""
return f"{self.action} {self.timestamp}"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI, the string representation of the message is what is going to be in the email body when people ask to be notified of these messages in FMN. You may want to put a little more text there, but it's just a non-blocking suggestion.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@harriebird Can we have this covered by the tests? It would be annoying if it would break.

@abompard action is a human-readable description of the action, so that looks okay. But I'm not sure whether to include the timestamp here.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah you can put the timestamp there, it's really up to you. I would set something more human readable though, or just make it return self.summary if you can't or don't want to have a longer text.

@harriebird harriebird force-pushed the feature/add-weblate-fedora-messaging-schema branch 4 times, most recently from c19c1d5 to d31bf35 Compare October 14, 2024 16:39
@harriebird harriebird force-pushed the feature/add-weblate-fedora-messaging-schema branch from d31bf35 to b0b129e Compare October 14, 2024 16:48
@harriebird
Copy link
Contributor Author

harriebird commented Oct 14, 2024

Hi everyone, I just updated the code based on your comments. Below are the changes made:

  • Reverted changes in setup.py and moved the entry_points declaration to setup.cfg
  • Transferred fedora-messaging and jsonschema[format] to requirements-test.txt
  • Updated the summary property implementation
  • Updated the usernames property implementation
  • Changed the id property into change_id
  • Used get method in accessing the body dictionary
  • Added pip install -e . command in the dependency install of test.yml workflow

@property
def agent_name(self) -> str:
"""The username who cause the action."""
return self.body.get("user", "")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there is no agent name, it should be None, not an empty string

@property
def change_id(self) -> int:
"""Return the change ID."""
return self.body.get("change_id")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the JSON schema, change_id is required, you can be sure it'll always be there, so you can use self.body["change_id"]. (just a suggestion, get() will work too)

@property
def action(self) -> str:
"""Return the change verbose name."""
return self.body.get("action")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the JSON schema, action is required, you can be sure it'll always be there, so you can use self.body["action"].

@property
def timestamp(self) -> datetime:
"""Return the timestamp of the change."""
return self.body.get("timestamp")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the JSON schema, timestamp is required, you can be sure it'll always be there, so you can use self.body["timestamp"].

def summary(self) -> str:
"""Return the message summary."""
return "{} event{} occurred in {}.".format(
self.body.get("action"),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same remark here. By the way, you can use self.action: if you end up moving the data in the dictionary, you'll only have to update it in one place.

" done by {}".format(self.body.get("user"))
if self.body.get("user", None)
else "",
self.body.get("timestamp"),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same remark here

"""Return the usernames involved."""
users = []
users += [self.author] if self.author else []
users += [self.user] if self.user else []

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or something like:

users = list(sorted({name for name in (self.author, self.user) if name}))

(just a suggestion, not a blocker)

It is useful to convert to a list in the end, because sorted() returns an iterator, not an actual list.

Copy link

@abompard abompard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! 👍

@harriebird harriebird force-pushed the feature/add-weblate-fedora-messaging-schema branch 3 times, most recently from bd73b1a to c866110 Compare October 22, 2024 18:16
@harriebird harriebird force-pushed the feature/add-weblate-fedora-messaging-schema branch from c866110 to 5a629b9 Compare October 22, 2024 18:27
weblate_schemas/messages.py Outdated Show resolved Hide resolved
weblate_schemas/messages.py Outdated Show resolved Hide resolved
weblate_schemas/messages.py Outdated Show resolved Hide resolved

def __str__(self) -> str:
"""Return a human-readable representation of the message."""
return f"{self.action} {self.timestamp}"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@harriebird Can we have this covered by the tests? It would be annoying if it would break.

@abompard action is a human-readable description of the action, so that looks okay. But I'm not sure whether to include the timestamp here.

weblate_schemas/messages.py Outdated Show resolved Hide resolved
weblate_schemas/messages.py Outdated Show resolved Hide resolved
@nijel nijel enabled auto-merge (squash) November 6, 2024 09:11
@nijel
Copy link
Member

nijel commented Nov 6, 2024

I've scheduled this for merge because I want to release this package soon anyway. In case we hit some issues later, those can be fixed in the next release.

@nijel nijel self-assigned this Nov 6, 2024
@nijel nijel disabled auto-merge November 6, 2024 09:43
@nijel nijel merged commit 73b608e into WeblateOrg:main Nov 6, 2024
7 of 11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants