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

Move installed modules code to utils #2429

Merged
merged 21 commits into from Nov 24, 2023
Merged

Conversation

sentrivana
Copy link
Contributor

@sentrivana sentrivana commented Oct 10, 2023

...and introduce a package_version helper function to use in integrations.

Even though we're now using the _get_installed_modules function in many different places, it still lives in sentry_sdk.integrations.modules. This PR:

  • moves _get_installed_modules (and related helpers) to utils.py
  • introduces a new package_version helper function (also in utils.py) that finds out and parses the version of a package in one go.

@sentrivana sentrivana enabled auto-merge (squash) October 12, 2023 12:16
auto-merge was automatically disabled October 24, 2023 12:28

Pull Request is not mergeable

Copy link
Member

@szokeasaurusrex szokeasaurusrex left a comment

Choose a reason for hiding this comment

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

I added two comments with some changes we might consider; however, I think the code is already good as is. I don't feel strongly about the comments, so it is okay with me if you would prefer to merge this PR as is.

Comment on lines +1608 to +1613
def _get_installed_modules():
# type: () -> Dict[str, str]
global _installed_modules
if _installed_modules is None:
_installed_modules = dict(_generate_installed_modules())
return _installed_modules
Copy link
Member

Choose a reason for hiding this comment

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

Would it perhaps be a good idea to place this code, along with the _installed_modules into a static class, so we can avoid having a global variable? I guess the static class would still effectively be storing a global state, so perhaps it makes only a small difference here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We could wrap this in a static class but then it'd be a bit inconsistent to have some installed modules related code in the class (the _get_installed_modules function above + the _installed_modules var) and some of it outside (e.g. the package_version helper). We could put everything in the class, but it's not great API to have to then import the class to use a small utility function. Also, you technically are introducing a global variable in any case, it's just about whether turning the whole thing into a class brings any additional benefits. I'd prefer to keep this as is if that's ok with you.

@@ -488,3 +500,60 @@ def test_get_error_message(error, expected_result):
exc_value.detail = error
raise Exception
assert get_error_message(exc_value) == expected_result(exc_value)


def test_installed_modules():
Copy link
Member

Choose a reason for hiding this comment

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

It looks to me as though this test is simply generating the installed module information in the same or a similar way that the actual code does it in utils.py. I would prefer that we somehow compare against a manually generated output, though, since this test will fail to detect a case where something changes in the importlib or pkg_resources modules that causes the test and the actual code to break in the same way, and it is also more difficult by reading this test case to determine what the intended output is.

Perhaps we can somehow mock out the installed modules so that we can manually generate the expected output, but admittedly doing this may be somewhat complicated. I also don't mind if we delete this test case, or replace it with a test case that simply calls the function and ensures we don't get an error, since I am unsure that it adds much value since we are just repeating the code from the function we are testing.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So this test is a bit unconventional. On py versions where only one of importlib.metadata, pkg_resources exists, it's exactly as you write -- it isn't testing much. It only makes sense on py versions that have both importlib.metadata and pkg_resources, since in that case it compares whether our ways of getting and normalizing the package name yield the same result for packages from both importlib.metadata and pkg_resources.

@sentrivana sentrivana self-assigned this Nov 6, 2023
Copy link
Member

@antonpirker antonpirker left a comment

Choose a reason for hiding this comment

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

Looks good to me.
And the unconventional test is also fine with me as it tests at least something :-)

@sentrivana sentrivana enabled auto-merge (squash) November 24, 2023 09:48
auto-merge was automatically disabled November 24, 2023 09:50

Pull Request is not mergeable

@sentrivana sentrivana enabled auto-merge (squash) November 24, 2023 09:53
@sentrivana sentrivana merged commit 5ee3c18 into master Nov 24, 2023
468 checks passed
@sentrivana sentrivana deleted the ivana/package-version-helper branch November 24, 2023 10:02
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.

None yet

3 participants