mirror of
https://github.com/danieldemus/pyp2spec.git
synced 2026-07-29 05:34:22 +02:00
199 lines
5.3 KiB
Python
199 lines
5.3 KiB
Python
import sys
|
|
|
|
from datetime import date
|
|
from subprocess import check_output
|
|
from urllib.parse import urlparse
|
|
|
|
import click
|
|
import requests
|
|
import tomli_w
|
|
|
|
|
|
def get_pypi_metadata(package_name):
|
|
pypi_index = f'https://pypi.org/pypi/{package_name}/json'
|
|
response = requests.get(pypi_index)
|
|
return response.json()
|
|
|
|
|
|
def changelog_head(email, name, changelog_date):
|
|
""" :returns f'{date} {name} <{email}>'"""
|
|
if not changelog_date:
|
|
changelog_date = (date.today()).strftime('%a %b %d %Y')
|
|
|
|
if email or name:
|
|
return f'{changelog_date} {name} <{email}>'
|
|
|
|
result = check_output(['rpmdev-packager'])
|
|
result = result.decode().strip()
|
|
return f'{changelog_date} {result}'
|
|
|
|
|
|
def changelog_msg(message):
|
|
if message:
|
|
return message
|
|
return f"Package generated with pyp2spec"
|
|
|
|
|
|
def get_release(release):
|
|
if release:
|
|
return release
|
|
return "1"
|
|
|
|
|
|
def get_project_url(package_data):
|
|
try:
|
|
return package_data["info"]["project_urls"]["Homepage"]
|
|
# It may happen that no Homepage is listed with the project
|
|
# In this case fall back to the safe PyPI URL
|
|
except KeyError:
|
|
return package_data["info"]["package_url"]
|
|
|
|
|
|
def get_python_name(pypi_name):
|
|
if pypi_name.startswith("python"):
|
|
return pypi_name
|
|
else:
|
|
return f"python-{pypi_name}"
|
|
|
|
|
|
def get_module_name(pypi_name):
|
|
"""A naive way to get probable module name: replace any occurrence
|
|
of '-' in package PyPI name with '_' and return the result."""
|
|
|
|
return [pypi_name.replace("-", "_")]
|
|
|
|
|
|
def get_source_url(pypi_name):
|
|
return "%{pypi_source " + pypi_name + "}"
|
|
|
|
|
|
def get_archive_name(filename):
|
|
return "-".join(filename.split("-")[:-1])
|
|
|
|
|
|
def get_version(version, package_data):
|
|
if version:
|
|
return version
|
|
# Custom version was not provided, return the latest available
|
|
return package_data["info"]["version"]
|
|
|
|
|
|
def get_summary(summary, package_data):
|
|
if summary:
|
|
return summary
|
|
return package_data["info"]["summary"]
|
|
|
|
|
|
def is_url(package):
|
|
parsed = urlparse(package)
|
|
if all((parsed.scheme, parsed.netloc)):
|
|
return True
|
|
return False
|
|
|
|
|
|
def create_config_contents(package, description=None, release=None,
|
|
message=None, email=None, name=None, version=None, summary=None, date=None):
|
|
"""Use `package_data` to create the whole config contents.
|
|
Return contents.
|
|
"""
|
|
contents = {}
|
|
|
|
# These items don't depend on information gathered from the package source
|
|
contents["changelog_msg"] = changelog_msg(message)
|
|
contents["changelog_head"] = changelog_head(email, name, date)
|
|
contents["release"] = get_release(release)
|
|
|
|
# `package` is not a URL -> it's a package name, look for it on PyPI
|
|
if not is_url(package):
|
|
package_data = get_pypi_metadata(package)
|
|
|
|
pypi_name = package_data["info"]["name"]
|
|
contents["pypi_name"] = pypi_name
|
|
contents["python_name"] = get_python_name(pypi_name)
|
|
contents["modules"] = get_module_name(pypi_name)
|
|
version = get_version(version, package_data)
|
|
contents["version"] = version
|
|
contents["summary"] = get_summary(summary, package_data)
|
|
contents["license"] = package_data["info"]["license"]
|
|
contents["url"] = get_project_url(package_data)
|
|
contents["source"] = get_source_url(pypi_name)
|
|
|
|
for entry in package_data["releases"][version]:
|
|
if entry["packagetype"] == "sdist":
|
|
contents["archive_name"] = get_archive_name(entry["filename"])
|
|
|
|
contents["description"] = description
|
|
return contents
|
|
|
|
|
|
def write_config(contents, output=None):
|
|
"""Write config file to a given destination.
|
|
If none is provided, save it to current directory with package name as file name.
|
|
"""
|
|
if output:
|
|
dest = output
|
|
else:
|
|
package = contents["python_name"]
|
|
dest = f"./{package}.conf"
|
|
with open(dest, "wb") as f:
|
|
tomli_w.dump(contents, f, multiline_strings=True)
|
|
return dest
|
|
|
|
|
|
@click.command()
|
|
@click.argument(
|
|
"package")
|
|
@click.option(
|
|
"--output", "-o",
|
|
help="Provide custom output for configuration file",
|
|
)
|
|
@click.option(
|
|
"--description", "-d",
|
|
help="Provide description for the package",
|
|
)
|
|
@click.option(
|
|
"--release", "-r",
|
|
help="Provide custom release (corresponds with Release in spec file)",
|
|
)
|
|
@click.option(
|
|
"--message", "-m",
|
|
help="Provide changelog message for the package",
|
|
)
|
|
@click.option(
|
|
"--email", "-e",
|
|
help="Provide e-mail for changelog",
|
|
)
|
|
@click.option(
|
|
"--packagername", "-n",
|
|
help="Provide packager name for changelog",
|
|
)
|
|
@click.option(
|
|
"--version", "-v",
|
|
help="Provide package version to query PyPI for",
|
|
)
|
|
@click.option(
|
|
"--summary", "-s",
|
|
help="Provide custom package summary",
|
|
)
|
|
@click.option(
|
|
"--date",
|
|
help="Provide custom date for changelog",
|
|
)
|
|
def main(package, output, description, release, message, email, packagername,
|
|
version, summary, date):
|
|
|
|
if not description:
|
|
print("Description wasn't provided. "
|
|
"Rerun the script with package description.")
|
|
sys.exit(1)
|
|
|
|
contents = create_config_contents(
|
|
package, description, release, message, email, packagername, version,
|
|
summary, date
|
|
)
|
|
write_config(contents, output)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|