diff --git a/twine/__init__.py b/twine/__init__.py index 051b92e3..68cb6e0f 100644 --- a/twine/__init__.py +++ b/twine/__init__.py @@ -23,7 +23,7 @@ __summary__ = "Collection of utilities for interacting with PyPI" __uri__ = "https://github.com/pypa/twine" -__version__ = "1.4.0" +__version__ = "1.5.0.dev1" __author__ = "Donald Stufft and individual contributors" __email__ = "donald@stufft.io" diff --git a/twine/commands/register.py b/twine/commands/register.py new file mode 100644 index 00000000..85de60f3 --- /dev/null +++ b/twine/commands/register.py @@ -0,0 +1,78 @@ +# Copyright 2014 Ian Cordasco +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import requests + +from twine import common +from twine import utils + + +def post_data(distribution, action): + """Take the distribution and the action and generate post data.""" + meta = distribution.metadata + data = { + ':action': action, + 'metadata_version': '1.0', + 'name': meta.get_name(), + 'version': meta.get_version(), + 'summary': meta.get_description(), + 'home_page': meta.get_url(), + 'author': meta.get_contact(), + 'author_email': meta.get_contact_email(), + 'license': meta.get_licence(), + 'description': meta.get_long_description(), + 'keywords': meta.get_keywords(), + 'platform': meta.get_platforms(), + 'classifiers': meta.get_classifiers(), + 'download_url': meta.get_download_url(), + # PEP 314 + 'provides': meta.get_provides(), + 'requires': meta.get_requires(), + 'obsoletes': meta.get_obsoletes(), + } + if data['provides'] or data['requires'] or data['obsoletes']: + data['metadata_version'] = '1.1' + # We rely on requests to generate the multipart form-data for us. In order + # to not rely on the requests-toolbelt, we need to send tuples as values + # so the values are not interpreted as files. + return dict((k, ('', data[k])) for k in data) + + +def register(repository, username, password, **kwargs): + # Get our config from ~/.pypirc + try: + config = utils.get_config()[repository] + except KeyError: + raise KeyError( + "Missing '{0}' section from the configuration file".format( + repository, + ), + ) + + username = utils.get_username(username, config) + password = utils.get_password(password, config) + + session = requests.Session() + session.auth = (username, password) + distribution = None + resp = session.post(config["repository"], + files=post_data(distribution, "submit")) + resp.close() + session.close() + resp.raise_for_status() + + +def main(args): + parser = common.common_arguments("twine register") + args = parser.parse_args(args) + register(**vars(args)) diff --git a/twine/commands/upload.py b/twine/commands/upload.py index 98ba6416..0dfa2220 100644 --- a/twine/commands/upload.py +++ b/twine/commands/upload.py @@ -14,7 +14,6 @@ from __future__ import absolute_import, division, print_function from __future__ import unicode_literals -import argparse import glob import hashlib import os.path @@ -30,6 +29,7 @@ import pkg_resources import requests +from twine.common import common_arguments from twine.utils import get_config, get_username, get_password from twine.wheel import Wheel from twine.wininst import WinInst @@ -219,12 +219,7 @@ def upload(dists, repository, sign, identity, username, password, comment, def main(args): - parser = argparse.ArgumentParser(prog="twine upload") - parser.add_argument( - "-r", "--repository", - default="pypi", - help="The repository to upload the files to (default: %(default)s)", - ) + parser = common_arguments("twine upload") parser.add_argument( "-s", "--sign", action="store_true", @@ -240,14 +235,6 @@ def main(args): "-i", "--identity", help="GPG identity used to sign files", ) - parser.add_argument( - "-u", "--username", - help="The username to authenticate to the repository as", - ) - parser.add_argument( - "-p", "--password", - help="The password to authenticate to the repository with", - ) parser.add_argument( "-c", "--comment", help="The comment to include with the distribution file", diff --git a/twine/common.py b/twine/common.py new file mode 100644 index 00000000..83465fc6 --- /dev/null +++ b/twine/common.py @@ -0,0 +1,19 @@ +import argparse + + +def common_arguments(prog): + parser = argparse.ArgumentParser(prog=prog) + parser.add_argument( + "-r", "--repository", + default="pypi", + help="The repository to upload the files to (default: %(default)s)", + ) + parser.add_argument( + "-u", "--username", + help="The username to authenticate to the repository as", + ) + parser.add_argument( + "-p", "--password", + help="The password to authenticate to the repository with", + ) + return parser