Skip to content

Conversation

lmeyerov
Copy link
Contributor

@lmeyerov lmeyerov commented Aug 1, 2025

Add comprehensive documentation for GraphOperation type constraints in let() bindings.

lmeyerov and others added 13 commits July 28, 2025 01:59
This commit extracts the massive GFQL implementation from PR #708 containing:

CORE IMPLEMENTATION (19 new files):
- AST classes: ASTLet, ASTRemoteGraph, ASTRef, ASTCall (700+ lines)
- Let execution engine: chain_let.py (445 lines)
- Call execution system: call_executor.py + call_safelist.py (500+ lines)
- Validation framework: gfql_validation/ (650+ lines)
- Comprehensive test suite: 10 new test files (3,000+ lines)

UNIFIED API & DEPRECATIONS (11 modified files):
- New methods: gfql(), gfql_remote(), gfql_remote_shape()
- Deprecation warnings: chain() → gfql(), chain_remote() → gfql_remote()
- Public API: Added let, remote, ref, call aliases
- Type distribution: py.typed marker for mypy/pyright support

MODIFIED NOTEBOOKS (CI-tested):
- demos/gfql/gfql_remote.ipynb
- demos/gfql/gfql_validation_fundamentals.ipynb
- demos/more_examples/graphistry_features/hop_and_chain_graph_pattern_mining.ipynb

CONFIGURATION:
- CI: Updated workflows for validation and type checking
- CHANGELOG: Added comprehensive feature documentation
- Packaging: MANIFEST.in and setup.cfg updates

This represents the complete GFQL v2 implementation with:
- DAG patterns with Let bindings and dependency resolution
- Safe method execution with call operations and safelist
- Comprehensive validation framework with structured error reporting
- Full backward compatibility with deprecation warnings
- Extensive test coverage ensuring quality

Supersedes incomplete PRs #715/#716 which missed 80%+ of this implementation.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
- Change base class ASTSerializable._get_child_validators return type from List to Sequence
- Update all implementing methods to return Sequence['ASTSerializable']
- Fixes mypy variance errors where implementations returned List[ASTPredicate] or List[ASTObject]
- Sequence is covariant, allowing subtype returns while maintaining type safety

Resolves python-lint-types CI failures in Python 3.10 and 3.11.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
- Add group_in_a_box_layout to SAFELIST_V1 with full parameter validation
- Support all parameters: partition_alg, layout_alg, positioning, colors, engine
- Add comprehensive pytest validation tests
- Verified parameter types match implementation signature
Add strict type validation to ensure let() bindings only accept operations
that produce Plottable objects, preventing invalid wavefront matchers.

## Core Changes

### GraphOperation Type Definition
- Add `GraphOperation` union type for valid let() binding values
- Includes: Plottable, Chain, ASTRef, ASTCall, ASTRemoteGraph, ASTLet
- Excludes: bare ASTNode, ASTEdge (wavefront matchers need context)

### ASTLet Validation Enhancement
- Add GraphOperation validation in ASTLet._validate_fields()
- Clear error messages guide users to valid operation types
- Support mixed JSON/native object construction with validate parameter

### Dict Convenience Auto-Wrapping
- Auto-wrap ASTNode/ASTEdge in Chain when dict passed to gfql()
- Preserves user convenience while enforcing type safety
- Maintains backward compatibility for dict-based GFQL queries

### Public API Cleanup
- Remove chain_let from public API (use gfql() instead)
- Improve error handling in hop() and chain execution
- Add defensive checks for DataFrame column consistency

## Testing
- 110 tests pass (100% success rate for runnable tests)
- 4 tests skipped (documented runtime execution issues)
- Comprehensive test coverage for all GraphOperation types
- End-to-end validation of type constraints and error handling

## Breaking Changes
- let() now rejects bare n() and e() - wrap in Chain([n()]) instead
- chain_let() removed from public API - use gfql() instead

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
Fixed critical bug where chain() left output graphs with inconsistent edge bindings
when temporary 'index' column was added and removed during processing.

**Root Cause**:
- chain() added 'index' column if g._edge was None
- After processing, 'index' column was dropped from DataFrame
- But output graph still had _edge='index' pointing to non-existent column
- Subsequent chain() calls failed with "Column 'index' not found"

**Solution**:
- Store original edge binding before modification
- Restore original binding when creating output graph after dropping 'index' column
- Ensures edge binding stays consistent with actual DataFrame columns

**Impact**:
- Fixes 4 previously skipped tests that relied on chaining chain() results
- Enables proper ASTRef chain execution in chain_let DAGs
- No regressions - all existing functionality preserved

**Tests Fixed**:
- test_node_edge_combination
- test_dag_with_node_and_chainref
- test_diamond_pattern_execution
- test_parallel_independent_branches

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
The ASTLet constructor temporarily stores different types during JSON/native
processing before validation. Added type ignores to suppress mypy errors
while maintaining runtime type safety through validation.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
- Fix E261: Add proper spacing before inline comments
- Fix W292: Add newline at end of graph_operation.py
- Fix F402: Add noqa comment for legitimate dynamic Chain import
- Keep original Chain name for dynamic imports (no renaming needed)

The TYPE_CHECKING import is only for type hints and doesn't conflict
with runtime dynamic imports used to avoid circular dependencies.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
Removed unused imports:
- typing.Any
- pandas as pd
- Engine from graphistry.Engine

Also fixed line length for import statement.

Note: hop.py has many other whitespace/formatting issues that need cleanup.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
- Remove trailing whitespace in graph_operation.py
- Remove unused pandas import from ast.py
- Remove unused GFQLValidationError import
- Fix line length for typing imports

Note: Many other whitespace and unused predicate imports remain
but these are pre-existing issues not introduced by our changes.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
Fixed only the issues that actually fail CI (not ignored by lint.sh):
- F841: Renamed unused variables with underscore prefix and noqa
- W292: Added newline at end of test_graph_operation.py

The previous commits fixing F401, W291, W293 were not necessary
as these are ignored by bin/lint.sh, but they don't hurt either.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
Fixed mypy errors where runtime hasattr() checks aren't recognized:
- ast.py:790: to_json() call on objects that may not have it
- validate_schema.py:44: chain attribute access on Union type

Both cases already have proper runtime checks, just need type ignores.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
- Add comprehensive Let bindings section explaining GraphOperation types
- Document accepted types: Chain, Plottable, ASTRef, ASTCall, etc.
- Document rejected types: bare ASTNode/ASTEdge (wavefront matchers)
- Add E201 error documentation with clear examples
- Add migration guide for updating existing let() code
- Explain why Chain wrapper is needed for wavefront operations

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
@lmeyerov lmeyerov force-pushed the feature/graph-operation-docs-v2 branch from 251792a to 70ed79f Compare August 2, 2025 00:27
@lmeyerov
Copy link
Contributor Author

Concerns about PR Redundancy

After analyzing the PR stack, I've identified potential conflicts:

Issue: Both PR #725 and #726 modify the same file () with different approaches:

Conflict: These changes cannot both be merged as-is since they modify the same file section.

Analysis:

Recommendation: Consider consolidating the focused GraphOperation documentation from #726 into the comprehensive approach in #725, then close this PR to avoid conflicts.

What are your thoughts on this approach?

@lmeyerov
Copy link
Contributor Author

Concerns about PR Redundancy

After analyzing the PR stack, I've identified potential conflicts:

Issue: Both PR #725 and #726 modify the same file with different approaches:

Conflict: These changes cannot both be merged as-is since they modify the same file section.

Analysis:

Recommendation: Consider consolidating the focused GraphOperation documentation from #726 into the comprehensive approach in #725, then close this PR to avoid conflicts.

What are your thoughts on this approach?

@lmeyerov lmeyerov force-pushed the feature/graph-operation-code branch from c80f17f to 969cec0 Compare August 11, 2025 04:54
@lmeyerov
Copy link
Contributor Author

Closing this PR due to structural issues.

Issues identified:

E201 documentation status:

Using #725 as the primary documentation PR for GraphOperation features.

@lmeyerov lmeyerov closed this Sep 21, 2025
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.

1 participant