Conversation
|
@liamhuber I started looking into the possibility of including variables as well. Frankly I'm also not really convinced but I still would like to explore the possibility |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #164 +/- ##
==========================================
- Coverage 97.97% 97.65% -0.32%
==========================================
Files 34 34
Lines 2268 2305 +37
==========================================
+ Hits 2222 2251 +29
- Misses 46 54 +8 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
I just had a discussion with @XzzX and we think we can keep the current implementation is maybe not quite as useless as I had imagined, because with this implementation it is now possible to throw an error as soon as an external variable is used. |
Failing cleanly is infinitely better than looking like everything is well-provenanced when it isn't. However, I still think that restricting "ok locally defined stuff" to mean "don't use any symbols outside your function definition" is going to turn out to be a more annoying, more restrictive, more-work solution than telling people "you'll have to use well-versioned code to contribute to the KG". As an intermediate step towards catching and leveraging these external symbols, this still seems like solid progress though. |
There was a problem hiding this comment.
Pull request overview
This PR updates dependency_parser to infer function dependencies by identifying undefined names in a function’s AST (including from type hints) and resolving those names from the function’s scope, recursively exploring unversioned objects.
Changes:
- Replaced call-graph-based dependency crawling with undefined-variable detection and resolution.
- Added
UndefinedVariableVisitorandfind_undefined_variableshelpers to drive dependency discovery. - Reworked
test_dependency_parserto focus on the new undefined-variable behavior and mocked resolution.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 7 comments.
| File | Description |
|---|---|
flowrep/models/parsers/dependency_parser.py |
Introduces undefined-name visitor + new dependency collection approach based on scope resolution and version availability. |
tests/unit/models/parsers/test_dependency_parser.py |
Replaces prior call-dependency tests with new tests for splitting, undefined-name detection, and mocked dependency discovery. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR modifies the dependency parsing logic to detect names used-but-not-defined in a function’s source (e.g., globals/type-hint symbols) and resolve them to objects for version tracking, as part of the ongoing dependency-crawling work from #155.
Changes:
- Added an AST visitor (
UndefinedVariableVisitor) plusfind_undefined_variablesto extract undefined symbols from source code. - Reworked
get_call_dependenciesto resolve those symbols viaobject_scopeand optionally recurse for unversioned objects. - Replaced the prior call-graph oriented unit tests with new tests focused on undefined-variable discovery and resolution.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
flowrep/models/parsers/dependency_parser.py |
Adds undefined-variable detection and updates dependency collection logic to resolve those symbols to objects. |
tests/unit/models/parsers/test_dependency_parser.py |
Rewrites tests to cover the new undefined-variable based behavior and mocked resolution paths. |
Comments suppressed due to low confidence (1)
tests/unit/models/parsers/test_dependency_parser.py:102
test_type_hintsreferencesnpbut the module isn't imported/defined anywhere in this test module, so definingtest_functionwill raiseNameError(or laterget_call_dependencieswill fail resolving it). Also, CI envs here don't include optional deps like NumPy, so importing NumPy in the test would be brittle. Define a small module-level dummynp(with an.arrayattribute) or use a stdlib object instead so the test is self-contained and doesn't add a new dependency.
if __name__ == "__main__":
unittest.main()
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| def visit_Name(self, node): | ||
| if isinstance(node.ctx, ast.Load): # Variable is being used | ||
| self.used_vars.add(node.id) | ||
| elif isinstance(node.ctx, ast.Store): # Variable is being defined | ||
| self.defined_vars.add(node.id) | ||
|
|
||
| def visit_FunctionDef(self, node): | ||
| # Add the function name itself to defined variables | ||
| self.defined_vars.add(node.name) | ||
| # Add function arguments to defined variables | ||
| for arg in node.args.args: | ||
| self.defined_vars.add(arg.arg) | ||
| self.generic_visit(node) | ||
|
|
||
| def visit_AsyncFunctionDef(self, node): | ||
| # Add the async function name itself to defined variables | ||
| self.defined_vars.add(node.name) | ||
| # Add async function arguments to defined variables | ||
| for arg in node.args.args: | ||
| self.defined_vars.add(arg.arg) |
| def get_call_dependencies( | ||
| func_or_var: Callable | object, | ||
| version_scraping: versions.VersionScrapingMap | None = None, | ||
| _call_dependencies: CallDependencies | None = None, | ||
| _visited: set[str] | None = None, | ||
| ) -> CallDependencies: | ||
|
|
||
| call_dependencies: CallDependencies = _call_dependencies or {} | ||
| visited: set[str] = _visited or set() | ||
|
|
||
| func_fqn = versions.VersionInfo.of(func_or_var).fully_qualified_name | ||
| if func_fqn in visited: | ||
| return call_dependencies | ||
| visited.add(func_fqn) | ||
|
|
||
| # Find variables that are used but not defined | ||
| scope = object_scope.get_scope(func_or_var) | ||
| for item in find_undefined_variables(func_or_var): | ||
| obj = object_scope.resolve_attribute_to_object(item, scope) | ||
| info = versions.VersionInfo.of(obj, version_scraping=version_scraping) | ||
| call_dependencies[info] = obj | ||
|
|
||
| if info.version is None: | ||
| get_call_dependencies(obj, version_scraping, call_dependencies, visited) | ||
| return call_dependencies |
|
@copilot Rewrite |
|
@samwaseda I've opened a new pull request, #190, to work on those changes. Once the pull request is ready, I'll request review from you. |
Co-authored-by: samwaseda <37879103+samwaseda@users.noreply.github.com>
Detect local arguments and functions used in a function
Following the effort in #155, I started trying to parse variables as well. Edits will follow....