Skip to content

Instantly share code, notes, and snippets.

@tanbro
Last active June 26, 2023 06:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tanbro/552bd2584edc032626d1642dbbc831cb to your computer and use it in GitHub Desktop.
Save tanbro/552bd2584edc032626d1642dbbc831cb to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
"""
# Report PyProject version
The tool print python source code project's version from pip install report with a dry-run.
The project MUST have a `pyproject.toml` file with metadata defined in it!
- On non-western language Windows, environment `PYTHONUTF8` may be in need .
- For Python version smaller than 3.11, package `toml` is required. To install it:
pip install "toml;python_version<'3.11'"
"""
import argparse
import json
import shlex
import subprocess
import sys
from pathlib import Path
from textwrap import dedent
if sys.version_info >= (3, 11):
import tomllib
else:
try:
import toml as tomllib
except ImportError as err:
msg = dedent(
f"""
{err}
You can install the library by execute:
{sys.executable} -m pip install toml
"""
).lstrip()
print(msg)
raise
PIP_REPORT_COMMAND_FRAGMENT = [
"pip",
"install",
"--disable-pip-version-check",
"--dry-run",
"--no-deps",
"--ignore-installed",
"--ignore-requires-python",
"--quiet",
"--report",
"-",
]
def set_args():
parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument(
"--python",
"-P",
default=f"{sys.executable}",
help="Run `pip` module of this Python executable (default: %(default)s).",
)
help_static_version = (
"Print static version defined in pyproject.toml if possible when the option is true; "
"Or always print dynamic version from pip install report. "
"(default=%(default)r)"
)
if sys.version_info >= (3, 9):
parser.add_argument(
"--static-version",
action=argparse.BooleanOptionalAction,
default=False,
help=help_static_version,
)
else:
parser.add_argument(
"--static-version",
action="store_true",
help=help_static_version,
)
parser.add_argument(
"--pip-options",
metavar="OPTIONS",
help="Extra options to be supplied to the pip in a string.",
)
parser.add_argument(
"dir",
metavar="DIR",
nargs="?",
default=".",
help="Report version of the Python source code project in this directory. A pyproject.toml file MUST be in it. (default=%(default)r)",
)
return parser.parse_args()
def main(args):
with Path(args.dir).joinpath("pyproject.toml").open("rb") as fp:
pyproject = tomllib.load(fp)
project = pyproject["project"]
project_name = project["name"]
if args.static_version:
try:
project_version = project["version"] # try find Static version
except KeyError:
pass
else: # Print static version, then exit
print(project_version)
return
# Dynamic version!
completed_process = subprocess.run(
(
[args.python, "-m"]
+ PIP_REPORT_COMMAND_FRAGMENT
+ (shlex.split(args.pip_options) if args.pip_options else [])
+ [args.dir]
),
capture_output=True,
check=True,
text=True,
)
report = json.loads(completed_process.stdout)
for package in report["install"]:
if package["metadata"]["name"] == project_name:
print(package["metadata"]["version"])
break
if __name__ == "__main__":
exit(main(set_args()))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment