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

feat(python,rust): build_info() provides detailed information how polars was built #5423

Merged
merged 3 commits into from
Nov 6, 2022

Conversation

slonik-az
Copy link
Contributor

@slonik-az slonik-az commented Nov 4, 2022

(resolves #5422)

[new functionality is behind build_info feature gate]

polars.build_info() returns dictionary with hierarchically organized information about how this polars was built -- features enabled, dependencies and their versions, compilation details, optimization/debug flags, rustc version, git commit information, and more.

This information is useful when troubleshooting polars deployments.

@github-actions github-actions bot added enhancement New feature or an improvement of an existing feature python Related to Python Polars rust Related to Rust Polars labels Nov 4, 2022
Copy link
Collaborator

@zundertj zundertj left a comment

Choose a reason for hiding this comment

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

Left a couple of code-specific questions and suggestions (Python only).

On a high level, the most important question: why not integrate this information in pl.show_versions?

And could you add an example output here (and in the docstring), so we know what we are talking about?



build_info = _closure_()
del _closure_
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why would the method need to be deleted?

Copy link
Contributor Author

@slonik-az slonik-az Nov 5, 2022

Choose a reason for hiding this comment

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

_closure_ should be called only once. After it is deleted it cannot be called at all. Otherwise a user can call it again as

from polars.show_versions import _closure_
_closure_()

Python unfortunately does not have proper private visibility. Closures is the only way to emulate private.

Copy link
Contributor Author

@slonik-az slonik-az Nov 5, 2022

Choose a reason for hiding this comment

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

I decided to refactor the code. _closure_ is gone altogether and code is simplified.

def build_info(): moved from polars/show_versions.py into polars/build_info.py to avoid any confusion with show_versions(). Pushed PR update.

def test_build_info() -> None:
build_info = pl.build_info()
features = build_info.get("features", {})
if features:
Copy link
Collaborator

Choose a reason for hiding this comment

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

It would be nice if we can test both branches here somehow.

Copy link
Contributor Author

@slonik-az slonik-az Nov 5, 2022

Choose a reason for hiding this comment

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

I think the code already tests both branches:

  1. When build_info feature gate in enabled features field is populated and tested for presence of BUILD_INFO feature
  2. Otherwise without build_info feature the only element present in dictionary is version and its presence is tested in the else part of the code (line 18, not shown in the snippet).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Moved testing code into test_build_info.py file.

return build_info


build_info = _closure_()
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is there a specific reason to run this on import polars? Why not leave as a method?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is a function at the same level as show_versions and version. If changing to method, of what class?

@@ -69,3 +70,36 @@ def _get_dep_version(dep_name: str) -> str:

# all our dependencies (as of 2022-08-11) implement __version__
return module_version


def _closure_() -> _typing_.Callable[[], _typing_.Any]:
Copy link
Collaborator

Choose a reason for hiding this comment

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

The method name could be more descriptive. I propose to call this build_info, and import this method directly in __init__.py

Copy link
Contributor Author

@slonik-az slonik-az Nov 5, 2022

Choose a reason for hiding this comment

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

The function is already called build_info. Closure _closure_ is here to create a private scope and initiate private variables that build_info() returns. Closure executed once and then deleted. This is standard way to overcome python's limitation of not having proper private or static variables.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

_closure_() is gone now. See the updated PR.

@@ -3,6 +3,7 @@
import importlib
import platform
import sys
import typing as _typing_
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why not do from typing import Callable, Any? The underscores are not needed either?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good call. I will change it and import only specific elements of typing.

@slonik-az
Copy link
Contributor Author

slonik-az commented Nov 5, 2022

On a high level, the most important question: why not integrate this information in pl.show_versions?

pl.show_versions() is already quite heavy and does not return anything (None). pl.build_info() returns a large dictionary with lots of build information (for example, 200+ rust dependencies with their versions). It should be up to a user what parts of this tree to process and how. Also pl.show_versions() indiscriminately prints to stdout in a fixed format without possibility to redirect output -- an anti-pattern if used for logging. Among other things pl.build_info() is aimed at use in logging and deployment troubleshooting.

To avoid confusion with show_versions(), I can move build_info() into its own file build_info.py. The same for the tests.

@slonik-az
Copy link
Contributor Author

And could you add an example output here (and in the docstring), so we know what we are talking about?

Good call. I will show structure of the output in the docstring. The returned dictionary is large (it lists all 200+ polars rust dependencies and their versions). For brevity, I will include partial output.

…ars was built

(implements pola-rs#5422)

[new functionality is behind `build_info` feature gate]

`polars.build_info()` returns dictionary with hierarchically organized information about how this
polars was built -- features enabled, dependencies and their versions, compilation details,
optimization/debug flags, rustc version, git commit information, and more.

This information is useful when troubleshooting polars deployments.
Many thanks to @zundertj for insightful comments/suggestions.
@slonik-az
Copy link
Contributor Author

Refactored python code per code review. Many thanks to @zundertj for insightful comments/suggestions. Also rebased the PR onto the latest master.

@zundertj
Copy link
Collaborator

zundertj commented Nov 6, 2022

@slonik-az : one thing I should have mentioned: could you also add an entry to this function in the Python API reference? I know this one is merged, but in a new PR.

@ritchie46
Copy link
Member

Thanks @slonik-az for the PR and thank you @zundertj for the review.

@ritchie46 ritchie46 merged commit 1f45cb4 into pola-rs:master Nov 6, 2022
@slonik-az
Copy link
Contributor Author

could you also add an entry to this function in the Python API reference? I know this one is merged, but in a new PR.

Will do.

@slonik-az
Copy link
Contributor Author

could you also add an entry to this function in the Python API reference? I know this one is merged, but in a new PR.

Done in PR #5442

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or an improvement of an existing feature python Related to Python Polars rust Related to Rust Polars
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Provide detailed build information in the installed polars
3 participants