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

Present supported API #194

Open
reinout opened this issue Jul 6, 2016 · 7 comments
Open

Present supported API #194

reinout opened this issue Jul 6, 2016 · 7 comments

Comments

@reinout
Copy link
Contributor

reinout commented Jul 6, 2016

Zest.releaser uses twine as an API when uploading files to pypi. It calls upload() directly. But ece3711, which is in the recent 1.7.x releases, broke the API as there are now two extra mandatory arguments.

So...

  • Is it OK to use twine as an API by importing from it? I'm getting the feeling it is more intended as a stand-alone CLI tool, just like pip. And not like something that is intended to be imported and used as a library.
  • A function with 10 (now 12) mandatory arguments is not really nice as an API. Is there another function that's better to use? Why are it mandatory arguments instead of keyword arguments?
@sigmavirus24
Copy link
Member

I've been clear on past issues that we don't consider twine.commands.* to be a public API. What I've been working towards, however, is something semi-public in twine.{exceptions,package,repository}.

If you look at how the upload command works, it roughly does:

  • Create a Repository from URL and credentials (username, password)
  • Set SSL bits (if necessary) (the two new parameters you mention)
  • Create a PackageFile from its filename (PackageFile.from_filename)
  • Find a signature or sign it (if the user wants us to)
  • Upload the PackageFile instance using Repository#upload

That said, I've had neither time, nor the inclination to document these because I wouldn't consider them entirely stable APIs. I still have a desire to iterate on them and really no one else has been really asking for much of a stable API. They have accepted that we don't have one and use the internals as they see fit completely accepting that they may see breakage.

@htgoebel
Copy link

@sigmavirus24 Is there some "high level" API, which an be considered stable? What about e.g. twine.cli.dispatch()?

Rational: I need to add support for --sign or detection of signature-files (.asc) to zest.releaser. zest.releaser currently is not able to upload signatures: it implements upload following your advice above, thus uploading each file on its own, and Repository#upload will skip any .asc file.

Implementing this, I found myself re-implementing quite some parts of twine (esp. twine.commands.upload#upload and – even more important – using a lot more functions of which it is unclear whether they are stable and public. IMHO this is not the way to go. Imagine twine gaining more and more functionality and the PyPi API changing.

For example using twine.cli.dispatch() would solve this issue – if it is to be considered public. Using this function would add some overhead for parsing arguments, etc., but on the other hand it would allow to use twine like on the command-line (without the overhead of starting a new process).

@bhrutledge
Copy link
Contributor

@sigmavirus24 How are you feeling about this and PR #361? Worth keeping open and discussing as a feature request?

@jaraco jaraco changed the title Usability as an API? Present supported API May 31, 2020
@jaraco jaraco added documentation enhancement feature request and removed question Discussion/decision needed from maintainers labels May 31, 2020
@jaraco
Copy link
Member

jaraco commented May 31, 2020

I have some sympathies with the critiques made in #361. In particular, I do agree the "hello world" of a twine API should be short and sweet. A client shouldn't need to orchestrate a series of objects to perform a basic operation. The API should provide sane defaults very similar to how the command-line interface behaves. Ideally, the programmatic API and CLI would both be built on a common foundation, something like 'actions' with 'args' where args have 'defaults'.

It seems that the main users requesting this functionality would be satisfied with a simple entry point that exposes the various twine commands via their CLI interface.

@jaraco
Copy link
Member

jaraco commented Jun 20, 2020

In the feature/commands-api branch, I've drafted the concept where the twine commands are exposed as functions in twine.api. To invoke upload:

import twine.api
args = []  # args as would be passed to subprocess.Popen
twine.api.upload(args)

I'm not sure if this approach is viable or where it would not be. It surely doesn't provide any high-level abstractions or sophistication around the mechanics of twine; it simply provides a shortcut to the behavior in-process. I did note that for some values of args (e.g. --help), a SystemExit is raised by the ArgumentParser. I suspect that's an ignorable behavior if it only applies to --help.

@sigmavirus24
Copy link
Member

@jaraco just because folks are using that out of desperation now doesn't mean we should irrevocably make that the API. It's not something we could walk back and the api you've described is not an API I'd ever want to use as a 3rd party. (Passing in an argparse.Namespace or a list of arguments that are undocumented)

@jaraco
Copy link
Member

jaraco commented Apr 3, 2024

I've pushed that branch to refs/archive/feature/commands-api and deleted it. Basically all it did was expose all of the registered commands.

import pkg_resources


def install_commands():
    globals().update(
        (ep.name, ep.load())
        for ep in pkg_resources.iter_entry_points(group='twine.registered_commands')
    )


install_commands()
del install_commands

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants