Files
pyp2spec/pyp2conf.py
T

192 lines
5.4 KiB
Python

from datetime import date
from subprocess import check_output
from urllib.parse import urlparse
import click
import requests
import tomli_w
class PypiPackage():
def __init__(self, package, session=None):
self.package = package
self.package_data = self.get_package_metadata(session)
@property
def pypi_name(self):
return self.package_data["info"]["name"]
def get_package_metadata(self, session):
pkg_index = f'https://pypi.org/pypi/{self.package}/json'
s = session or requests.Session()
response = s.get(pkg_index)
return response.json()
def python_name(self):
if self.pypi_name.startswith("python"):
return self.pypi_name
else:
return f"python-{self.pypi_name}"
def modules(self):
"""A naive way to get probable module name: replace any occurrence
of '-' in package PyPI name with '_' and return the result."""
return [self.pypi_name.replace("-", "_")]
def source_url(self):
return "%{pypi_source " + self.pypi_name + "}"
def version(self):
return self.package_data["info"]["version"]
def license(self):
return self.package_data["info"]["license"]
def summary(self):
return self.package_data["info"]["summary"]
def project_url(self):
try:
return self.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 self.package_data["info"]["package_url"]
def archive_name(self, version):
for entry in self.package_data["releases"][version]:
if entry["packagetype"] == "sdist":
return "-".join(entry["filename"].split("-")[:-1])
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():
"""Return a default changelog message."""
return "Package generated with pyp2spec"
def get_description(package):
"""Return a default package description."""
return f"This is package '{package}' generated automatically by pyp2spec."
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, session=None):
"""Use `package` and provided kwargs to create the whole config contents.
Return contents.
"""
contents = {}
# These items don't depend on information gathered from the package source
contents["changelog_msg"] = message or changelog_msg()
contents["changelog_head"] = changelog_head(email, name, date)
contents["release"] = release or "1"
contents["description"] = description or get_description(package)
# `package` is not a URL -> it's a package name, look for it on PyPI
if not is_url(package):
pkg = PypiPackage(package, session)
contents["pypi_name"] = pkg.pypi_name
contents["python_name"] = pkg.python_name()
contents["modules"] = pkg.modules()
contents["summary"] = summary or pkg.summary()
contents["license"] = pkg.license()
contents["url"] = pkg.project_url()
contents["source"] = pkg.source_url()
version = version or pkg.version()
contents["version"] = version
contents["archive_name"] = pkg.archive_name(version)
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):
contents = create_config_contents(
package, description, release, message, email, packagername, version,
summary, date
)
write_config(contents, output)
if __name__ == "__main__":
main()