Skip to content

Detect local arguments and functions used in a function#164

Open
samwaseda wants to merge 32 commits intomainfrom
args
Open

Detect local arguments and functions used in a function#164
samwaseda wants to merge 32 commits intomainfrom
args

Conversation

@samwaseda
Copy link
Member

@samwaseda samwaseda commented Feb 26, 2026

Following the effort in #155, I started trying to parse variables as well. Edits will follow....

@github-actions
Copy link

Binder 👈 Launch a binder notebook on branch pyiron/flowrep/args

@samwaseda samwaseda changed the base branch from main to crawler February 26, 2026 08:36
@samwaseda samwaseda marked this pull request as draft February 26, 2026 08:37
@samwaseda
Copy link
Member Author

@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
Copy link

codecov bot commented Feb 26, 2026

Codecov Report

❌ Patch coverage is 89.23077% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 97.65%. Comparing base (ef7ec85) to head (1e893de).

Files with missing lines Patch % Lines
flowrep/models/parsers/dependency_parser.py 89.23% 7 Missing ⚠️
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.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@samwaseda
Copy link
Member Author

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.

@liamhuber
Copy link
Member

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.

Base automatically changed from crawler to main February 27, 2026 07:20
@samwaseda samwaseda changed the title Detect arguments as well Detect local arguments and functions used in a function Mar 18, 2026
@samwaseda samwaseda requested a review from Copilot March 19, 2026 16:01
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

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 UndefinedVariableVisitor and find_undefined_variables helpers to drive dependency discovery.
  • Reworked test_dependency_parser to 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.

samwaseda and others added 4 commits March 19, 2026 17:12
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>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

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) plus find_undefined_variables to extract undefined symbols from source code.
  • Reworked get_call_dependencies to resolve those symbols via object_scope and 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_hints references np but the module isn't imported/defined anywhere in this test module, so defining test_function will raise NameError (or later get_call_dependencies will 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 dummy np (with an .array attribute) 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.

Comment on lines +44 to +63
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)
Comment on lines +104 to +128
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
@samwaseda
Copy link
Member Author

@copilot Rewrite UndefinedVariableVisitor to forbid local function definitions.

Copy link
Contributor

Copilot AI commented Mar 19, 2026

@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.

Copilot AI and others added 2 commits March 19, 2026 18:10
Co-authored-by: samwaseda <37879103+samwaseda@users.noreply.github.com>
Detect local arguments and functions used in a function
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.

5 participants