Skip to content

feat: Ensure service account file exists before initializing credentials#386

Open
cacheflow wants to merge 3 commits into
olucurious:masterfrom
cacheflow:ensure-service-account-file-exists
Open

feat: Ensure service account file exists before initializing credentials#386
cacheflow wants to merge 3 commits into
olucurious:masterfrom
cacheflow:ensure-service-account-file-exists

Conversation

@cacheflow
Copy link
Copy Markdown

@cacheflow cacheflow commented May 5, 2026

This PR adds a validation check to ensure that the service_account_file path passed to FCM exists before attempting to initialize credentials using Google OAuth.

References #385.

@cacheflow
Copy link
Copy Markdown
Author

Hey @olucurious or @Niccari when y'all have a moment, can you review this PR?

Copy link
Copy Markdown
Contributor

@Niccari Niccari left a comment

Choose a reason for hiding this comment

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

Thanks for the fix! I've reviewed it and here are my comments below. I've also prepared a suggestion branch (https://github.com/Niccari/PyFCM/tree/fix-suggestion-ensure-service-account-file-exists) — feel free to pull it in if it looks good.

Comment thread pyfcm/baseapi.py Outdated
missing_account_file = not path.isfile(self._service_account_file)

if missing_account_file:
raise InvalidDataError(f"The service account file you passed does not exist at '{path}'. "
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

{path} here refers to the os.path module imported above, not the file path string. This will render as something like <module 'posixpath' from '...'> in the error message. It should be {self._service_account_file}.

Suggested change
raise InvalidDataError(f"The service account file you passed does not exist at '{path}'. "
if not path.isfile(self._service_account_file):
raise InvalidDataError(
f"The service account file you passed does not exist at '{self._service_account_file}'. "
"Ensure it does not have any typos and exists."
)

Copy link
Copy Markdown
Author

@cacheflow cacheflow May 16, 2026

Choose a reason for hiding this comment

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

Thanks for the feedback. I've incorporated the change.

Comment thread tests/test_fcm.py Outdated

def test_push_service_with_incorrect_service_account_file():
try:
# figure out why this goddamn test is not running
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This looks like a leftover note. Could you remove it before merging? (FYI, the test does run — notify() calls send_requestrequest_headers_get_access_token_initialize_credentials.)

Suggested change
# figure out why this goddamn test is not running
fcm = FCMNotification(service_account_file='./foo.json', project_id=None, credentials=None)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Done! Sorry about that. 😆

Copy link
Copy Markdown
Contributor

@Niccari Niccari left a comment

Choose a reason for hiding this comment

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

Thanks for the updates — the error message and the comment are both addressed now. However, this revision introduces a runtime regression I'd like to flag before merge. See the inline comment.

I've updated my suggestion branch (https://github.com/Niccari/PyFCM/tree/fix-suggestion-ensure-service-account-file-exists), rebased on this PR's latest commit (see: 08041af), which restores the correct class and adds a regression test. Feel free to pull it in.

Comment thread pyfcm/baseapi.py Outdated
raise InvalidDataError(f"The service account file you passed does not exist at '{self._service_account_file}'. "
"Ensure it does not have any typos and exists."
)
self.credentials = Credentials.from_service_account_file(
Copy link
Copy Markdown
Contributor

@Niccari Niccari May 16, 2026

Choose a reason for hiding this comment

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

This is a runtime regression. Credentials here is google.oauth2.credentials.Credentials (the user/OAuth2 access-token class), which has no from_service_account_file classmethod. With a valid service_account_file, this raises:

AttributeError: type object 'Credentials' has no attribute 'from_service_account_file'

Only google.oauth2.service_account.Credentials provides from_service_account_file, which is why the original code imported and used service_account. The removal of from google.oauth2 import service_account (line 11) needs to be reverted as well.

Suggested change
self.credentials = Credentials.from_service_account_file(
self.credentials = service_account.Credentials.from_service_account_file(

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

You're right. I saw two credential files in the upstream Google lib and pulled in the wrong one.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Thanks again. I've brought in the changes from your branch.

Copy link
Copy Markdown
Contributor

@Niccari Niccari left a comment

Choose a reason for hiding this comment

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

Thanks, LGTM! 🎉

note - As a non-maintainer reviewer I don't have permission to trigger it.
so @olucurious would need to approve the workflow run to get CI to execute.

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.

2 participants