Upload
This model represents a package upload to a pypi compatible server.
Code
from typing import List, Optional
from pydantic import BaseModel, Field
class PackageUpload(BaseModel):
metadata_version: str
name: str
version: str
filename: str
content: bytes
pyversion: str
filetype: str
sha256_digest: str
md5_digest: str
blake2_256_digest: str
action: str = Field(..., alias=":action")
protocol_version: str
requires_dist: List[str] = None
provides_extra: List[str] = None
description_content_type: Optional[str] = None
requires_python: Optional[str] = None
summary: Optional[str] = None
maintainer_email: Optional[str] = None
license: Optional[str] = None
project_urls: Optional[List[str]] = None
author_email: Optional[str] = None
keywords: Optional[List[str]] = None
classifiers: Optional[List[str]] = None
Example
The following Flask example will call callback(...) with any uploaded package:
from flask import Flask, request
from werkzeug.utils import secure_filename
app = Flask(__name__)
def callback(package: PackageUpload):
print(package.name, package.version)
return "OK", 200
@app.route("/legacy", methods=["POST"])
def upload():
form_data = {
"metadata_version": request.form.get("metadata_version"),
"name": request.form.get("name"),
"summary": request.form.get("summary"),
"license": request.form.get("license"),
"version": request.form.get("version"),
"description_content_type": request.form.get("description_content_type"),
"requires_python": request.form.get("requires_python"),
"pyversion": request.form.get("pyversion"),
"author_email": request.form.get("author_email"),
"maintainer_email": request.form.get("maintainer_email"),
"filetype": request.form.get("filetype"),
"sha256_digest": request.form.get("sha256_digest"),
"md5_digest": request.form.get("md5_digest"),
"blake2_256_digest": request.form.get("blake2_256_digest"),
":action": request.form.get(":action"),
"protocol_version": request.form.get("protocol_version"),
"project_urls": request.form.getlist("project_urls"),
"requires_dist": request.form.getlist("requires_dist"),
"provides_extra": request.form.getlist("provides_extra"),
"classifiers": request.form.getlist("classifiers"),
"keywords": request.form.getlist("keywords"),
}
if uploaded_file := request.files.get("content"):
form_data["filename"] = secure_filename(uploaded_file.filename)
form_data["content"] = uploaded_file.read()
try:
package_upload = PackageUpload(**form_data)
except Exception as e:
return str(e), 400
return callback(package_upload)
else:
return "No file uploaded", 400
The following twine command should work and the server will print out name and version of all the packages
twine upload --repository-url http://localhost:5000/legacy dist/*