fix(profiler): prevent filtering target package name in module discovery - #18072
fix(profiler): prevent filtering target package name in module discovery#18072hebaalazzeh wants to merge 3 commits into
Conversation
c608b53 to
7af75c7
Compare
There was a problem hiding this comment.
Code Review
This pull request introduces PEP 0810 explicit lazy imports (lazy_modules) across several packages in google-cloud-core and updates the import profiler script to better handle namespace packages. The review feedback suggests placing the lazy_modules definitions before import statements in accordance with PEP 8, which would also eliminate the need for .flake8 E402 bypasses and typing imports. Additionally, the feedback points out a logic issue in the import profiler's package filtering that causes false positives for packages like google-cloud-build, recommending a more specific exception for google-cloud-testutils.
I am having trouble creating individual review comments. Click here to see my feedback.
scripts/import_profiler/profiler.py (413-424)
The current logic pkg_clean.endswith(top.replace("_", "")) introduces false positives for other packages whose names end with an ignored prefix.
For example:
- For
google-cloud-build,pkg_cleanis"googlecloudbuild". If a standard"build"directory exists,topis"build". Since"googlecloudbuild"ends with"build", the"build"directory will NOT be ignored, which is incorrect as it is just a build artifact directory. - For
google-cloud-notebooks, the"notebooks"directory (which contains Jupyter notebooks and is inignored_prefixes) will NOT be ignored because"googlecloudnotebooks"ends with"notebooks".
Since google-cloud-testutils is the only package in the repository whose top-level Python package is actually in ignored_prefixes (test_utils), we should make this exception specific to google-cloud-testutils and test_utils. This avoids false positives for all other packages.
ignored_prefixes = ("tests", "samples", "examples", "benchmark", "benchmarks", "third_party", "testing", "test_utils", "docs", "build", "dist", "bin", "ci", "scripts", "cloudbuild", "notebooks", "assets", "scratch", "specs")
ignored_starts = ("test_", "sample_", "bench_", "example_", "doc_", "notebook_")
filtered = []
for p in pkgs:
top = p.split(".")[0]
is_ignored_top = top in ignored_prefixes or top.startswith(ignored_starts)
if is_ignored_top and pkg == "google-cloud-testutils" and top == "test_utils":
is_ignored_top = False
if is_ignored_top or p in ("google", "google.cloud"):
continue
filtered.append(p)
7af75c7 to
4e3ba12
Compare
24d9a30 to
f24e53d
Compare
chalmerlowe
left a comment
There was a problem hiding this comment.
I am glad you jumped on this in an effort to get some of our other PRs unblocked.
Thanks.
I have some strong preferences for approaches that should make the code simpler, more readable, and more maintainable.
I also provide some tips and facts that may help with justifying why these changes are a good idea.
| ignored_prefixes = ("tests", "samples", "examples", "benchmark", "benchmarks", "third_party", "testing", "test_utils", "docs", "build", "dist", "bin", "ci", "scripts", "cloudbuild", "notebooks", "assets", "scratch", "specs") | ||
| ignored_starts = ("test_", "tests_", "sample_", "samples_", "bench_", "benchmarks_", "example_", "examples_", "doc_", "docs_", "notebook_", "notebooks_") | ||
|
|
||
| filtered = [] |
There was a problem hiding this comment.
#PREFERENCE
In line with the idea of making the approach a positive one (i.e. identify which packages to process) we can simplify this code, as well.
- We ditch the
continuekeyword which complicates understanding offorloops (in large measure it is basically agotostatement which makes for spaghetti code) - By skipping the
continue, we end up doing the thing we intend to do immediately after getting the answer to our question with zero intervening logic AND clear logic of why theappend()step is happening. That clean step-like logic can be lost when we use a negative formulation and we inject acontinue:
- "Should we process this?"
- "Yes?"
- "Cool, append to filtered"
| filtered = [] | |
| filtered = [] | |
| for p in pkgs: | |
| top = p.split(".")[0] | |
| if _should_process_namespace_package(top, pkg): | |
| filtered.append(p) | |
| runpy.run_path(profiler_path, run_name="__main__") | ||
|
|
||
|
|
||
| def test_should_ignore_namespace_package(): |
There was a problem hiding this comment.
#PREFERENCE
If we choose to go with the positive approach, then this test will need to be renamed and potentially inverted to ensure we are getting back the packages to process not packages to ignore.
| IGNORED_TOP_LEVEL_NAMES = { | ||
| "tests", "samples", "examples", "benchmark", "benchmarks", "third_party", | ||
| "testing", "test_utils", "docs", "build", "dist", "bin", "ci", "scripts", | ||
| "cloudbuild", "notebooks", "assets", "scratch", "specs" | ||
| } | ||
| IGNORED_NAME_PREFIXES = ( | ||
| "test_", "tests_", "sample_", "samples_", "bench_", "benchmarks_", | ||
| "example_", "examples_", "doc_", "docs_", "notebook_", "notebooks_" | ||
| ) |
There was a problem hiding this comment.
Can we determine the list programatically ? There could be information in setup.py that we can use to determine which namespaces should be profiled:
google-cloud-python/packages/bigframes/setup.py
Lines 113 to 121 in 9f1477c
Fix module resolution for packages like
google-cloud-testutilswhose top-level Python package (test_utils) was being filtered out byignored_prefixesin find_module_from_package.