Skip to content

Support keyword-only parameters and default values in decorated functions #31

Open
bastianhagedorn wants to merge 6 commits intomainfrom
bhagedorn/fix-kwargs-sanitize-configs
Open

Support keyword-only parameters and default values in decorated functions #31
bastianhagedorn wants to merge 6 commits intomainfrom
bhagedorn/fix-kwargs-sanitize-configs

Conversation

@bastianhagedorn
Copy link
Collaborator

Fix **kwargs handling and support keyword-only params and default values

Problem

_sanitize_configs and run_profile_session used len(sig.parameters) to count function parameters, which includes *args and **kwargs. This caused a spurious validation error when the decorated function had **kwargs in its signature. Keyword-only parameters (after *) were also unsupported since configs were passed via func(*c) which can't populate keyword-only args.

Additionally, parameters with default values could not be omitted from configs — users had to always provide values for every parameter, even those with sensible defaults.

Fix

  • **kwargs/*args handling: Exclude VAR_POSITIONAL and VAR_KEYWORD parameters from all parameter counting and config validation (4 locations across core.py, extraction.py, transformation.py).
  • Keyword-only parameter support: New _bind_config_to_signature helper maps config values to parameters in declaration order, passing keyword-only params as **kwargs to the function call.
  • Default value support: New _pad_config_with_defaults fills in missing trailing config values with defaults from the function signature. This happens in _sanitize_configs so the rest of the pipeline always sees full-length configs.
  • Transformation fixes: Value column is now explicitly cast to numeric after explode (was staying as object dtype), and groupby uses dropna=False to handle None/NaN default values in parameter columns.

Tests

  • test_function_with_kwargs**kwargs tolerated in signature
  • test_function_with_keyword_only_paramsdef f(x, *, y) works
  • test_function_with_args_and_keyword_onlydef f(x, *args, y, **kwargs) works
  • test_function_with_default_parameter — updated: omitting defaulted param now works
  • test_default_values_omitteddef f(x, y, z=64) with 2-element config
  • test_default_values_overridden — explicitly providing a defaulted param
  • test_keyword_only_default_omitteddef f(x, *, y=32) with 1-element config
  • test_too_few_config_args_rejected — negative: fewer args than required params
  • test_too_many_config_args_rejected — negative: more args than total params

Docs

  • core_concepts.rst: documents supported parameter kinds (regular, keyword-only, defaults, *args/**kwargs)
  • known_issues.rst: notes that *args/**kwargs are tolerated but ignored
  • _sanitize_configs docstring updated

bastianhagedorn and others added 6 commits March 6, 2026 10:50
len(sig.parameters) includes VAR_KEYWORD (**kwargs) and VAR_POSITIONAL
(*args) parameters, causing _sanitize_configs and run_profile_session to
reject valid configs with a spurious argument count mismatch error.

Fixed in 4 locations:
- core.py: _sanitize_configs (2 places)
- core.py: run_profile_session
- transformation.py: transform_df
- extraction.py: arg_arrays creation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add notes to core_concepts.rst, known_issues.rst, and the
_sanitize_configs docstring clarifying that configs are passed as
positional args only — *args and **kwargs in the function signature
are tolerated but always empty during profiling.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Keyword-only parameters (after * or *args) will fail at runtime
since configs are passed via func(*config). Update docs to be
precise about what parameter kinds are supported vs tolerated.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add _bind_config_to_signature to map config values to both positional
  and keyword-only parameters in declaration order
- Add _get_regular_params and _count_params helpers to exclude *args/**kwargs
- Add test_function_with_keyword_only_params, test_function_with_args_and_keyword_only,
  and test_too_many_config_args_rejected
- Update docs: keyword-only params are now supported, *args/**kwargs tolerated,
  default values still require explicit config values

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When configs provide fewer values than the function has parameters,
_sanitize_configs pads the configs with default values from the function
signature. This ensures the full pipeline (ncu subprocess, extraction,
transformation) always sees full-length configs.

Also fixes two pre-existing issues exposed by None defaults:
- transformation.py: Value column stays object dtype after explode,
  now explicitly converted to numeric before aggregation
- transformation.py: groupby now uses dropna=False to handle None/NaN
  values in function parameter columns

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove errors="coerce" from pd.to_numeric so non-numeric values
raise an error instead of being silently converted to NaN.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@copy-pr-bot
Copy link

copy-pr-bot bot commented Mar 6, 2026

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@copy-pr-bot
Copy link

copy-pr-bot bot commented Mar 6, 2026

/ok to test

@bastianhagedorn, there was an error processing your request: E1

See the following link for more information: https://docs.gha-runners.nvidia.com/cpr/e/1/

@bastianhagedorn
Copy link
Collaborator Author

/ok to test 19e7f56

@acollins3
Copy link
Collaborator

Shame we can't support *args and **kwargs. This is just because there is no way to map a config tuple to *args and **kwargs right?

Maybe we could improve this in a follow up MR. Instead of just passing configs as simple tuples, we could pass a Config object whose arguments can be fully mapped to the profiled function (including to *args and **kwargs).

For example something like this:

@nsight.analyze.kernel(configs=[
    Config(1, 2, foo=3, bar=4)
])
def benchmark(x, y, **kwargs):
    ....

The arguments passed to the Config contructor could be mapped directly to those in the profiled funciton.

And to maintain backwards compatibility, (x,y,z) can be implicitly converted to Config(x,y,z)

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.

2 participants