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

Using main instead of run in subcommands leads to unexpected behavior #622

Open
2 tasks done
MaxDesiatov opened this issue Mar 10, 2024 · 1 comment
Open
2 tasks done
Labels
bug Something isn't working

Comments

@MaxDesiatov
Copy link
Member

When accidentally defining main instead of run in subcommands, no warning or error is shown, but the subcommand itself either displays a help message or swallows all arguments with no output.

ArgumentParser version: 1.2.0 and 1.3.0 or the main branch, for example.
Swift version: Apple Swift version 6.0-dev (LLVM ce41a43bba95b2b, Swift 1a840948a0905df), also reproducible with Swift 5.10.0 from Xcode 15.3.0

Checklist

  • If possible, I've reproduced the issue using the main branch of this package
  • I've searched for existing GitHub issues

Steps to Reproduce

Build and run an executable that has only this code:

import ArgumentParser

@main
struct Entrypoint: ParsableCommand {
  static let configuration = CommandConfiguration(
    subcommands: [Client.self, Server.self]
  )
}

struct Client: ParsableCommand {
  static func main() throws {
    print("Client!")
  }
}

struct Server: ParsableCommand {
  static func main() throws {
    print("Server!")
  }
}

Expected behavior

I realize that I should've defined run instead of main, but defining main in Entrypoint does work, that function is called, albeit with no argument parsing done IIUC. The actual behavior for subcommands is unexpected. The default implementation of ParsableCommand and AsyncParsableCommand should at least issue a warning, if possible, that no custom implementaiton of run is provided. Otherwise it's very easy to spend a long time debugging this issue.

I'd assume this can also be a very frustrating experience for first-time users who try to convert their existing @main entrypoint to ParsableCommand but don't realize they have to rename static func main() to func run().

Actual behavior

When running server or client subcommands on their own, a help message is shown, but not other output is produced:

USAGE: entrypoint server

OPTIONS:
  -h, --help              Show help information.

When passing any arguments like server foo bar, no output is produced whatsoever.

@MaxDesiatov MaxDesiatov added the bug Something isn't working label Mar 10, 2024
@natecook1000
Copy link
Member

Sorry you ran into this, @MaxDesiatov! There's a default implementation of the run() method for all parsable commands, since for intermediate commands in a command hierarchy, there's generally nothing to do other than printing the help screen. I'm reticent to add a warning to the output of a validly-built ParsableCommand type, even in debug mode, since I'm not sure of all the contexts where these commands run. Do you have any other suggestions about how we could surface this potential issue?


When passing any arguments like server foo bar, no output is produced whatsoever.

This sounds like a different issue – if you're able to create a reproducing command, could you file this separately? For the command above, I get this output:

$ entrypoint server foo bar
Error: 2 unexpected arguments: 'foo', 'bar'
Usage: entrypoint server
  See 'entrypoint server --help' for more information.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants