Repository navigation
Conversation
skrawcz
left a comment
There was a problem hiding this comment.
AI-assisted preliminary review — findings must be fixed or technically refuted before human review.
The example and absolute sibling-import handling address the main feedback from #824, and the basic create/append/skip tests pass. The implementation still needs significant work before it is safe as a CLI feature:
- It executes the target module through
module_from_source()merely to inspect signatures, so arbitrary top-level side effects run; package-relative imports still fail. Please use AST-based source discovery or justify the execution model and its security contract. - Generated calls discard Python parameter kinds/defaults. For example,
def f(x=1, *args, flag=False, **kwargs)becomesf(x, args, flag, kwargs), which changes semantics. Preserve positional/starred/keyword-only/double-starred arguments. - Append mode can add
pd.Seriesand module references to an existing file without adding the necessary imports, producing runtimeNameErrors. - Current Ruff reports F841 for
uses_pandasand F401 forad_hoc_utils.
Please fix these and add tests for top-level side effects, relative imports, postponed annotations, all parameter kinds/defaults, and append-mode imports—or technically refute why those cases are outside the command’s supported contract.
… kinds Review feedback on apache#1796: - discover functions and signatures with ast instead of importing the module, so generation cannot run top-level code and package-relative imports work - render each parameter with its own kind (positional-only, *args, keyword-only, **kwargs) and carry literal defaults into the stub; a default or annotation the generated file cannot resolve goes into the TODO comment instead - add the imports the new stubs need when appending; leave an unparsable file untouched instead of appending to it - skip async functions: a generated sync test cannot await them - tests for side effects, relative imports, postponed annotations, every parameter kind, append-mode imports, aliasing, CRLF and unparsable files
The previous insertion point was after the last top-level import, which could be below executable top-level code. Only the leading import block is considered now. Also narrows the README wording on call semantics and package-relative imports to what the tests cover.
|
@skrawcz Worked through the review in the commits on the branch. Signatures are read from the module source with Tests for top-level side effects, decorators, relative imports, postponed annotations, every One point I changed rather than fixed:
|
Implements #74: a
hamilton create-tests MODULE.pycommand that generates pytest-style unittest stubs for the Hamilton functions in a module. This revision works through the
review on the branch.
Changes
ast, so generating stubs no longerimports the module, cannot run its top-level code, and works for a module in a regular
package with a relative import (
pkg/orders.pygetsimport pkg.ordersand callspkg.orders.total_spend(...)).parameters are passed positionally,
*argsis unpacked, keyword-only parameters arepassed by name and
**kwargsis unpacked, sodef mixed(a, /, b, c=1, *args, flag=False, **kwargs)becomesmixed(a, b, c, *args, flag=flag, **kwargs). Every parameter is passed, so a stub doesnot exercise an omitted default; it is a stub to edit.
def bump(level=DEFAULT_LEVEL), and an annotation the generated file cannot resolve,such as one that needs
typing, are kept in the TODO comment instead, so the generatedfile has no undefined names.
import pandas as pdwhen the stubs callpd.*, plus the module import) above the first line of code in the file. A file that isnot valid Python is left untouched and the command reports an error.
async deffunctions are skipped: a generated synchronous test cannot await them.uses_pandasand the unusedad_hoc_utilsimport are gone (ruff F841/F401).How I tested this
Commands run from the repository root with
PYTHONPATHset to it, using a python 3.12.3venv holding pandas and the repository's pinned ruff 0.16.9:
python -m pytest tests/cli -q->27 passed.python -m pytest tests/cli/test_logic.py -q->24 passedwith this branch, and15 failed, 9 passedwithhamilton/cli/logic.pyreplaced by the version at thereviewed revision
ea3931band the same test file. Atea3931b, ruff reports the F841and F401 findings from the review.
ruff check hamilton/cli tests/cli->All checks passed!ruff format --check hamilton/cli/logic.py tests/cli/test_logic.py->2 files already formatted.imports, a package module with a relative import, and a module with a non-literal
default;
python -m pytest --collect-onlythen collects all four generated files.The new tests cover top-level side effects, decorators, relative imports, postponed
annotations, every parameter kind and default, non-literal defaults, append-mode imports,
aliased imports, CRLF files and an unparsable test file. Several of them import the
generated file for real, so an undefined name at import time fails the test.
Notes
prekis not installed on this machine; the pre-commit hooks' tools were run directly withthe repository's pinned versions (ruff 0.16.9 check and format).
Only synchronous module-level functions are stubbed. The generated test file imports the
target module when the tests run, so its top-level code runs then, as it would for any
test. Package detection covers directories with an
__init__.py; namespace packages arenot detected, and the generated import is relative to the package root.
Checklist
prekis not installed on this machine, so the hooks were not run as a hook;ruff checkandruff format --checkwere run directly at the pinned ruff 0.16.9 and both pass. The code is left cleaner/nicer than when first encountered.)