-
Notifications
You must be signed in to change notification settings - Fork 9
Log env packages #62
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
Log env packages #62
Conversation
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.
Hey @svalbuenaa, this looks really nice, thanks! I've left a few comments about reducing duplication, and making sure all the code is tested in all environments.
I haven't had chance to look over every line yet, so I may have a few more comments.
fancylog/fancylog.py
Outdated
write_python | ||
Log the Python version. Default: True | ||
write_env_packages | ||
Log the packages in the conda/pip environment. Default: True |
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.
AFAIK there's no such thing as a "pip" env.
Log the packages in the conda/pip environment. Default: True | |
Log the packages in the environment. Default: True |
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.
You are right, sorry about this. I will remove it in the next implementation I submit
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.
You can directly commit a GitHub review suggestion if you like, there's a button at the bottom of my comment.
fancylog/fancylog.py
Outdated
for pkg in conda_pkgs: | ||
self.file.write(f"{pkg['name']:20} {pkg['version']:15}\n") |
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.
Is it possible to just have one loop to reduce duplication of the code below?
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.
There is already just one loop there, right? Should I try to remove it altogether?
Or perhaps you meant these other lines with a conditional inside a for loop?:
for pkg in global_env_pkgs:
if pkg["name"] not in local_env_pkgs_names:
self.file.write(f"{pkg['name']:20} {pkg['version']:15}\n")
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.
yeah, i just meant there is some duplication. There's a similar (or identical) loop later on in the same file later on.
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.
got it. I am finishing implementing this with a helper method to avoid redundancies. Besides, I am currently working on logging the local and the global packages with only one call to
subprocess.run(["pip", "list"])
so the new implementation is also faster
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 is also implemented in the updated version
"""Python version section does not exist if logger | ||
is created with the parameter write_python_version as False. | ||
""" | ||
ver_header = f"{lateral_separator} PYTHON VERSION {lateral_separator}\n" |
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.
Nitpicking, but this could be a pytest fixture to reduce duplication
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.
I was not familiar with fixtures, thank you for the suggestion. I will try to combine the two tests this way
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.
They can take some getting used to, but they're very helpful to create "things" to be reused.
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.
By using
@pytest.mark.parametrize
decorators I can now combine the two pairs of header tests together
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.
The updated version uses parametrization to combine the tests for the presence/absence of the headers
conda_exe = os.environ["CONDA_EXE"] | ||
conda_list = subprocess.run( | ||
[conda_exe, "list", "--json"], capture_output=True, text=True |
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.
can this be tested in a non-conda env somehow? It won't currently be tested in our GitHub actions. Perhaps the return values could be mocked?
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.
I have tested this in both conda and venv. In my hands works well in both cases (i.e. when it is run in a conda env it logs the conda env packages and when it is run out of a conda env, such as in a venv, the appropriate packages are also logged). I will look into mocking return values and be back with an implementation
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.
Sorry I should have been clear, the tests run fine in all environments, but the issue is that if you're in a conda environment, the pip version won't be tested (and vice versa). This is particularly important with our automated tests that run in GitHub actions. It doesn't use conda, and so the conda version of the code could end up broken for a long time without us noticing.
Currently the the tests run some kind of system command, and then make sure the right section is added to the log. We don't really care if e.g. pip list
returns the right thing, that's someone elses job to test! We only care about testing fancylog code here. You can override what will be returned by these system commands to "pretend" you're in a specific environment, and then test the fancylog code as needed. There are a few ways of doing this, such as setting environmental variables, but the general process would be:
- Set up the environment to "appear" a certain way
- Run fancylog function, expecting it to run according to how the environment "appears"
- Check that everything runs properly
This may not be that clear, so let me know if I help any further.
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.
Thank you! I am currently working on this, I hope I have a new version with all the changes tomorrow or on Thursday
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.
I just commited changes, adding two new tests, one of which mocks the existence of a conda environment, and asserts the presence in the log of the appropriate texts, and another which mocks the lack of a conda environment.
duplication when logging pkgs Add tests mocking environment, remove duplication writing packages
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #62 +/- ##
==========================================
+ Coverage 71.51% 77.15% +5.63%
==========================================
Files 3 3
Lines 158 197 +39
==========================================
+ Hits 113 152 +39
Misses 45 45 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
d591bf9
to
fbce37d
Compare
I just added a new test to mock the lack of any local environment, so the patch coverage should be 100% now. Besides, my fork was 1 commit behind fancylog's main, so I merged this commit as well. |
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.
Thanks @svalbuenaa, this is great! I'm going to make a new release of fancylog now so we can start using it in other projects!
Thank you so much, @adamltyson. Looking forward to new contributions! |
Description
What is this PR
Why is this PR needed?
Include logging python version and environment packages as requested in issue #14
What does this PR do?
Two new methods (
write_python_version
andwrite_environment_packages
) have been added to theLoggingHeader
class.write_python_version
usessys.version
to logthe python version of the interpreterwrite_environment_packages
attempts to log the conda environment name and conda environment packages (using asubprocess
for the latter). Note that, in case fancylog is run within a conda environment, only the packages available in this environment are reported (as conda does not offer a way to use base environment packages from within an environment). In case there is no conda environment associated to the execution of fancylog (i.e. callingos.environ["CONDA_PREFIX"]
results in a KeyError), the method falls back to log the local and globally available packages. To do so, it uses two subprocesses (one callingpip list --local
for the locally available packages and another one callingpip list
for the globally available packages.write_environment_packages
logs all the locally available packages and any globally available package that is not also present in the local environment.References
Issue #14
How has this PR been tested?
Six new tests are added.
test_python_version_header_absent
asserts that there is noPYTHON VERSION
section header whenfancylog.start_logging
is called withwrite_python=False
.test_python_version_header_present
asserts that there is aPYTHON VERSION
section header whenfancylog.start_logging
is called withwrite_python=True
.test_correct_python_version_logged
asserts that the python version logged is correct. Thewrite_python_version
method logs the python version withsys.version
. The test compares the logged version with the output of callingplatform.python_version()
test_environment_header_absent
asserts that there is noENVIRONMENT
section header whenfancylog.start_logging
is called withwrite_env_packages=False
.test_environment_header_present
asserts that there is noENVIRONMENT
section header whenfancylog.start_logging
is called withwrite_env_packages=True
.test_correct_pkg_version_logged
If fancylog is run within a conda environment, the test asserts that the version logged for each package reported byconda list
is logged. Note that this way of accessing the versions of packages in the conda environment is the same that thewrite_environment_packages
uses to log the packages. If there is no conda environment the logged version of local environment packages, obtained through a subprocess call topip list --local
) is compared with the version obtained throughimportlib.metadata.distributions
.Is this a breaking change?
There is no breaking change. There is, however, a slow down in the logging process due to the calls to conda list or pip list, which take some time to be completed. This is mainly apparent in the time that it takes for unit tests to be completed.
Does this PR require an update to the documentation?
Methods and tests have been documented. No changes to README.md have been made, though.
Checklist: