You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix: address review feedback on pythonic skill and function signatures
Update SKILL.md to prevent three classes of issues: clarify that float
already accepts int per PEP 484 (avoiding redundant int | float that
fails ruff PYI041), add backward-compat rule for Category B so existing
Expr params aren't removed, and add guidance for inline coercion with
many optional nullable params instead of local helpers.
Replace regexp_instr's _to_raw() helper with inline coercion matching
the pattern used throughout the rest of the file.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
**Important:** In Python's type system (PEP 484), `float` already accepts `int` values, so `int | float` is redundant and will fail the `ruff` linter (rule PYI041). Use `float` alone when the Rust side accepts a float/numeric type — Python users can still pass integer literals like `log(10, col("a"))` or `power(col("a"), 3)` without issue. Only use `int` when the Rust side strictly requires an integer (e.g., `logical_int64()`).
108
+
107
109
#### Technique 3: Check `return_field_from_args()` for `scalar_arguments` usage
108
110
109
111
Functions that inspect literal values at query planning time use `args.scalar_arguments.get(n)` in their `return_field_from_args()` method. This indicates the argument is **expected to be a literal** for optimal behavior (e.g., to determine output type precision), but may still work as a column.
@@ -166,31 +168,30 @@ These are arguments where an `Expr` never makes sense because the value must be
166
168
167
169
**Type hint pattern:**`str`, `int`, `list[str]`, etc. (no `Expr` in the union)
168
170
169
-
**When to use:** When the argument is from a fixed enumeration or is always a compile-time constant:
170
-
-Date/time part names (`"year"`, `"month"`, `"day"`, etc.)
171
-
-Regex flags (`"g"`, `"i"`, etc.)
171
+
**When to use:** When the argument is from a fixed enumeration or is always a compile-time constant, **AND** the parameter was not previously typed as `Expr`:
172
+
-Separator in `concat_ws` (already typed as `str` in the Rust binding)
173
+
-Index in `array_position` (already typed as `int` in the Rust binding)
172
174
- Values that the Rust implementation already accepts as native types
173
175
176
+
**Backward compatibility rule:** If a parameter was previously typed as `Expr`, you **must** keep `Expr` in the union even if the Rust side requires a literal. Removing `Expr` would break existing user code like `date_part(lit("year"), col("a"))`. Use **Category A** instead — accept `Expr | str` — and let users who pass column expressions discover the runtime error from the Rust side. Never silently break backward compatibility.
### Category C: Arguments That Should Accept str as Column Name
@@ -269,6 +270,21 @@ if not isinstance(arg, Expr):
269
270
270
271
Do NOT create a new helper function for this — the inline check is clear and explicit. The project intentionally uses `ensure_expr()` to reject non-Expr values in contexts where coercion is not wanted; the pythonic coercion is the opposite pattern and should be visually distinct.
271
272
273
+
**Functions with many optional nullable parameters:** For parameters typed as `Expr | <type> | None`, combine the `None` check with the `isinstance` check inline. Repeat this for each parameter — do not factor it into a local helper function, even if the repetition feels verbose. Consistency across the file is more important than DRY within a single function.
274
+
275
+
```python
276
+
# For each optional parameter:
277
+
if start isnotNoneandnotisinstance(start, Expr):
278
+
start = Expr.literal(start)
279
+
280
+
# When passing to the Rust binding, extract .expr or pass None:
281
+
f.some_func(
282
+
values.expr,
283
+
start.expr if start isnotNoneelseNone,
284
+
n.expr if n isnotNoneelseNone,
285
+
)
286
+
```
287
+
272
288
## What NOT to Change
273
289
274
290
-**Do not change arguments that represent data columns.** If an argument is the primary data being operated on (e.g., the `string` in `left(string, n)` or the `array` in `array_sort(array)`), it should remain `Expr` only. Users should use `col()` for column references.
0 commit comments