Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keyword arguments are being accepted where they should be disallowed #5010

Closed
brandjon opened this issue Apr 12, 2018 · 14 comments
Closed

Keyword arguments are being accepted where they should be disallowed #5010

brandjon opened this issue Apr 12, 2018 · 14 comments
Assignees
Labels
P2 We'll consider working on this in future. (Assignee optional) type: bug

Comments

@brandjon
Copy link
Member

brandjon commented Apr 12, 2018

Some builtin functions accept keyword arguments where they should be positional-only. This creates unnecessary differences from Python and perhaps promotes bad style.

Example:

    # The fact that it's called "elements" is an implementation and documentation detail.
    # You shouldn't actually be able to call all() this way.
    all(elements=[True, False])

This comes from a bug in how Param#named is ignored for @SkylarkSignature. As we migrate @SkylarkSignature over to @SkylarkCallable, we've been inadvertently fixing this bug, thereby breaking backward compatibility without an incompatible change flag.

We've added Param#legacyNamed to prevent further breakages until we can control them with a flag (4baafac). For builtins that have already been migrated over, you may see errors like "unexpected keyword" or "parameter ... has no default value". If this impacts a significant number of users we could do a patch release to mark them legacyNamed. Otherwise it's better if users just update their code now since we want to be consistent with Python eventually anyway.

@brandjon
Copy link
Member Author

To be clear, only some builtin functions are affected. It looks like in the vast majority of cases, the functions that have been migrated are functions that take almost all their parameters by keyword anyway, so there shouldn't be much difference noticed.

@brandjon brandjon added type: bug P3 We're not considering working on this, but happy to review a PR. (No assignee) team-Starlark and removed category: extensibility > skylark labels Oct 18, 2018
@brandjon brandjon assigned c-parsons and unassigned brandjon Oct 18, 2018
@brandjon
Copy link
Member Author

Reassigning to Chris since he's managing Build Api related issues.

@c-parsons
Copy link
Contributor

This is on my radar for this quarter.

@c-parsons c-parsons added P2 We'll consider working on this in future. (Assignee optional) and removed P3 We're not considering working on this, but happy to review a PR. (No assignee) labels Jan 7, 2019
bazel-io pushed a commit that referenced this issue Jan 25, 2019
Note that converted parameter @param annotations need legacyNamed = true (and in some places, noneable = True) to retain compatibility with the bugginess of SkylarkSignature.

This facilitates followup to clean up these methods / parameters -- given the refactor, we can enforce some of these parameters are positional-only (subject to an --incompatible flag)

Progress toward #5010

RELNOTES: None.
PiperOrigin-RevId: 230975480
bazel-io pushed a commit that referenced this issue Jan 28, 2019
*** Reason for rollback ***

Breaks lots of tests with "method 'getattr' returns an object of invalid type SingletonSet" error; see b/123520324

*** Original change description ***

Convert MethodLibrary's SkylarkSignature methods to SkylarkCallable

Note that converted parameter @param annotations need legacyNamed = true (and in some places, noneable = True) to retain compatibility with the bugginess of SkylarkSignature.

This facilitates followup to clean up these methods / parameters -- given the refactor, we can enforce some of these parameters are positional-only (subject to an --incompatible flag)

Progress toward #5010

RELNOTES: None.
PiperOrigin-RevId: 231264758
weixiao-huang pushed a commit to weixiao-huang/bazel that referenced this issue Jan 31, 2019
Note that converted parameter @param annotations need legacyNamed = true (and in some places, noneable = True) to retain compatibility with the bugginess of SkylarkSignature.

This facilitates followup to clean up these methods / parameters -- given the refactor, we can enforce some of these parameters are positional-only (subject to an --incompatible flag)

Progress toward bazelbuild#5010

RELNOTES: None.
PiperOrigin-RevId: 230975480
weixiao-huang pushed a commit to weixiao-huang/bazel that referenced this issue Jan 31, 2019
*** Reason for rollback ***

Breaks lots of tests with "method 'getattr' returns an object of invalid type SingletonSet" error; see b/123520324

*** Original change description ***

Convert MethodLibrary's SkylarkSignature methods to SkylarkCallable

Note that converted parameter @param annotations need legacyNamed = true (and in some places, noneable = True) to retain compatibility with the bugginess of SkylarkSignature.

This facilitates followup to clean up these methods / parameters -- given the refactor, we can enforce some of these parameters are positional-only (subject to an --incompatible flag)

Progress toward bazelbuild#5010

RELNOTES: None.
PiperOrigin-RevId: 231264758
@laurentlb
Copy link
Contributor

cc @vladmos
Buildifier should help do the cleanup.

@vladmos
Copy link
Member

vladmos commented Feb 13, 2019

That looks like an easy cleanup for buildifier. Is there a complete list of functions with keywords that shouldn't be accepted?

@c-parsons
Copy link
Contributor

Any @Param annotation for a @SkylarkCallable which has legacyNamed = true falls into the category of "parameter we wish were not keyword".

Example:

@vladmos
Copy link
Member

vladmos commented Feb 21, 2019

The rule function has 11 arguments marked with legacyNamed = true, do we want all of them to become positional only?

@brandjon
Copy link
Member Author

It looks like legacyNamed was used when what's needed is the opposite -- "legacyPositional". rule() should ideally have no positional parameters.

@c-parsons
Copy link
Contributor

Summarizing our offline discussion:
legacyNamed is used in cases where, historically, we did not include named = True yet there was a bug present where it was as if named = True. Sometimes the exclusion was intentional, sometimes it wasn't. We have to make a call in many of these cases.

In cases where we make the call to make the param unspecifiable by name, this is technically a breaking change, so we need to attach it to an incompatible flag. We don't have the infrastructure to do this yet, so I'll need to implement this infrastructure.

@vladmos
Copy link
Member

vladmos commented Feb 22, 2019

There are the following usage of legacyNamed = true in Bazel:

  • provider: doc
  • rule: implementation, 10 more params
  • aspect: implementation, 8 more params
  • Label: label_string
  • FileType: types (deprecated anyway)
  • glob: include, exclude, exclude_directories
  • existing_rule: name
  • exports_files: srcs, visibility, licenses

String methods:

  • join: elements
  • lstrip, rstrip, strip: chars
  • replace: old, new, maxsplit
  • split, rsplit: sep, maxsplit
  • partition, rpartition: sep
  • rfind, find, rindex, index, count, endswith, startswith: sub, start, end
  • splitlines: keepends

Some builtins with keyword parameters that we'd probably like to make positional-only are @SkylarkSignatures and therefore don't have parameter maked with legacyNamed = true. Here are some examples:

  • all, any: elements
  • tuple, list, len, str, repr, bool, int, dir, type: x
  • dict: kwargs
  • enumerate: list
  • hash: value
  • range: start_or_stop, stop_or_none, step (even if we keep these we'll need to rename the first two)
  • hasattr: x, name
  • getattr: x, name, default (we may want to keep default, maybe also name?)
  • fail: msg, attr
  • select: x, no_match_error

I can make a buildifier fix for some of the parameters above and update it later as we agree on making more parameters positional. I guess all parameters called x should be positional, also elements for all and any, and list for enumerate. May I implement a fix for them? Should I include anything else?

@brandjon
Copy link
Member Author

We should (if it hasn't already been done) manually vet changes we make to arguments' keywordy-ness against the behavior of Python 2 and 3 to confirm we're making things more consistent. But even if a change is inconsistent, we can still go ahead with it if it helps readability.

@vladmos
Copy link
Member

vladmos commented Feb 25, 2019

Created a prototype: bazelbuild/buildtools#559

Once we agree on the list of functions and their arguments (it doesn't have to be the final list, can be extended any time), I'll merge it to buildifier.

@alandonovan
Copy link
Contributor

The important distinction is between core Starlark (e.g. getattr, splitlines) and the build language (e.g. fail, aspect). In the core, following Python, very few functions accept named arguments; int(base=...) is one of the rare exceptions. In the build language, and for user-defined macros, it's much more common for functions to accept or even require named arguments.

There is something ironic about the fact that the core is moving closer to Python (removing names) while the build language is moving towards Python3 by allowing users to require names in their functions. But I think it is the right thing.

bazel-io pushed a commit that referenced this issue Mar 5, 2019
This change creates --experimental_restrict_named_params to make all builtin Starlark parameters which are named via legacyNamed = true to instead be treated as positional-only.

This is a step on the path to cleaning up namedness of builtin Starlark parameters.

When we finalize the list of parameters which should truly be positional-only, we can change this flag to be prefixed with --incompatible instead of --experimental, as per the incompatible change policies.

Progress toward #5010.

RELNOTES: None.
PiperOrigin-RevId: 236898018
bazel-io pushed a commit that referenced this issue Apr 16, 2019
…larkCallable

Original description:
Note that converted parameter @param annotations need legacyNamed = true (and in some places, noneable = True) to retain compatibility with the bugginess of SkylarkSignature.

This facilitates followup to clean up these methods / parameters -- given the refactor, we can enforce some of these parameters are positional-only (subject to an --incompatible flag)

Progress toward #5010

RELNOTES: None.
PiperOrigin-RevId: 243891931
bazel-io pushed a commit that referenced this issue Apr 18, 2019
These were historically marked legacyNamed because the ability to refer to these parameters by keyword was not historically explicitly declared -- these were thus marked as "keyword-specifiable because of legacy infrastructure limitations". However, these particular usages are specified by keyword almost universally. We should therefore make explicit that specifying these parameters by keyword is intended behavior.

Progress toward #5010

RELNOTES: None.
PiperOrigin-RevId: 244210997
bazel-io pushed a commit that referenced this issue Apr 18, 2019
…d-specifiable

Progress toward #5010.

RELNOTES: None.
PiperOrigin-RevId: 244211187
bazel-io pushed a commit that referenced this issue Apr 18, 2019
These parameters were marked as "keyword-specifiable because of legacy infrastructure limitations". Some such parameters are specified by keyword almost universally: these parameters are migrated to "keyword-specifiable by intention". Others are kept under "legacyNamed" to be deprecated with --experimental_restrict_named_params

Progress toward #5010

RELNOTES: None.
PiperOrigin-RevId: 244216657
bazel-io pushed a commit that referenced this issue Apr 25, 2019
…ation

Progress toward #5010

RELNOTES: None.
PiperOrigin-RevId: 245320507
bazel-io pushed a commit that referenced this issue Apr 26, 2019
…estrict_named_params

This was always going to be an incompatible-style flag, but it was previously not fully implemented. Now it is.

Progress toward #8147 and #5010.

RELNOTES: Flag `--incompatible_restrict_named_params` is added. See #8147 for details.
PiperOrigin-RevId: 245428103
@c-parsons
Copy link
Contributor

Marking fixed, as #8147 is fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
P2 We'll consider working on this in future. (Assignee optional) type: bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants