Jens-G opened a new pull request, #3659:
URL: https://github.com/apache/thrift/pull/3659

   ## Summary
   
   Follow-up to THRIFT-5927 (Python keyword escaping) and THRIFT-6113 (its 
regression test wasn't actually running in CI). This is a regression introduced 
by THRIFT-5927 itself: before that fix, a service or function named after a 
Python keyword failed loudly at compile time (`validate_id()` against the full 
keyword set). THRIFT-5927 switched to escaping instead of rejecting, but only 
wired that escaping into struct/enum/field/exception generation and the service 
Client/Processor class bodies — not into two spots that the *same* 
`Thrift5927.thrift` test fixture already exercises (`service continue { import 
return(1: False while) throws (1: True yield) }`):
   
   1. `t_py_generator::generate_service()` builds the service's own module 
filename from the raw, unescaped service name. For a service named `continue` 
this emits `continue.py`. The file compiles fine in isolation, but neither 
normal import statement a consumer would write can reach it:
      ```
      >>> import ast
      >>> ast.parse('import thrift5927.continue')
      SyntaxError: invalid syntax
      >>> ast.parse('from thrift5927 import continue')
      SyntaxError: invalid syntax
      ```
   2. `t_py_generator::generate_service_remote()`, which emits the 
`<service>-remote` CLI helper script, never calls `maybe_escape_identifier()` 
at all. For this fixture it produced a script with three real syntax errors 
(confirmed with `py_compile`):
      ```python
      from thrift5927 import continue      # line 19 -- import target is a 
keyword
      client = continue.Client(protocol)   # line 104 -- keyword used as an 
identifier
      client.return(eval(args[0]),)        # line 111 -- keyword used as a 
method name
      ```
   
   The existing regression test didn't catch this because it only globs 
`**/*.py` for compileability; the `-remote` script intentionally has no `.py` 
suffix (same convention as every other language's generated CLI helper) and was 
invisible to that glob.
   
   ## Fix
   
   - Escape `service_name_` at its three real Python-identifier usages: the 
module filename, the remote script's `from <module> import <service>` line, and 
its `client = <service>.Client(...)` line.
   - Escape the function name used in the remote script's client dispatch call 
(`client.<function>(...)`), matching the already-escaped method name on the 
generated `Client` class.
   - Left untouched, on purpose: the `<service>-remote` filename itself (a 
shell-invoked filename, not a Python identifier -- keeping the literal IDL name 
is more useful for a human typing it), and the human-readable help/usage text 
and `sys.argv` command-word comparisons (string literals/values, not syntax 
positions -- a CLI user should still type and see the real IDL name).
   - Extended `test_keyword_escape.py` to also compile-check generated 
`*-remote` files.
   
   ## Out of scope
   
   Found while investigating, but not covered by the current fixture (no 
`extends` relationship in it) and not included here: `t_service` inheritance 
(`extends`) references and cross-module (included-file) type references also 
build Python import/attribute-access strings from unescaped names, via the same 
`generate_service()` extends-handling code and the shared 
`type_name()`/`type_to_spec_args()` helpers. That needs its own fixture and a 
closer look at those shared helpers, tracked separately rather than bundled 
into this fix.
   
   Also note: this PR does not run `clang-format` on the full 
`t_py_generator.cc` -- the file already has substantial pre-existing formatting 
drift unrelated to this change (not currently enforced by any CI check), and 
reformatting it wholesale seemed out of scope for a 4-line bug fix.
   
   ## Test plan
   
   - [x] Before the fix: extending the test's glob to include `*-remote` files 
reproduces the bug -- `py_compile` raises `SyntaxError: invalid syntax` on 
`continue-remote` line 19.
   - [x] After the fix: `test_keyword_escape.py` passes (`OK: All 6 generated 
Python files compile successfully`).
   - [x] Real import test (not just syntax): with the fixed compiler, `from 
thrift5927 import continue_`, `import thrift5927.continue_`, and 
`hasattr(continue_.Client, 'return_')` all succeed against the generated 
package plus the real `thrift` runtime library.
   - [x] Regression check: an ordinary (non-keyword) service name generates 
byte-identical output to before (verified with a throwaway `MyNormalService` 
fixture).
   
   ---
   This PR includes AI-assisted changes (Claude Code); see commit trailer.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to