Skip to content

Commit

Permalink
Add Support for Building from pyproject.toml [minor] (#5)
Browse files Browse the repository at this point in the history
* Add Support for Building from `pyproject.toml`

* update getting package name

* update getting package name - 2

* update python version logic
  • Loading branch information
ric-evans authored May 24, 2024
1 parent 23d196e commit f659152
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 37 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -157,4 +157,4 @@ cython_debug/
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
.idea/
33 changes: 27 additions & 6 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,20 +70,41 @@ runs:
# remove any old ones, then regenerate only what's needed
rm dependencies*.log || true
export PACKAGE_NAME=$(python3 ${{ github.action_path }}/utils/get_package_name.py setup.cfg)
export PACKAGE_NAME=$(python3 ${{ github.action_path }}/utils/get_package_name.py .)
export GITHUB_ACTION_PATH=${{ github.action_path }}
export ACTION_REPOSITORY="WIPACrepo/wipac-dev-py-setup-action"
# get python3 version (max)
export semver_RANGE=$(grep "python_requires =" -h setup.cfg | awk -F 'python_requires =' '{print $2}')
echo $semver_RANGE
# get python3 version (max) -- copied from https://github.com/WIPACrepo/wipac-dev-py-versions-action/blob/main/action.yml
export PACKAGE_MAX_PYTHON_VERSION=$(python -c '
import os
import os, re
from wipac_dev_tools import semver_parser_tools
semver_range = ""
if os.path.isfile("pyproject.toml"):
# ex: requires-python = ">=3.8, <3.13"
pat = re.compile(r"requires-python = \"(?P<semver_range>[^\"]+)\"$")
with open("pyproject.toml") as f:
for line in f:
if m := pat.match(line):
semver_range = m.group("semver_range")
if not semver_range:
raise Exception("could not find `requires-python` entry in pyproject.toml")
elif os.path.isfile("setup.cfg"):
# ex: python_requires = >=3.8, <3.13
pat = re.compile(r"python_requires = (?P<semver_range>.+)$")
with open("setup.cfg") as f:
for line in f:
if m := pat.match(line):
semver_range = m.group("semver_range")
if not semver_range:
raise Exception("could not find `python_requires` entry in setup.cfg")
else:
raise Exception("could not find pyproject.toml nor setup.cfg")
top_python = semver_parser_tools.get_latest_py3_release()
all_matches = semver_parser_tools.list_all_majmin_versions(
major=top_python[0],
semver_range=os.environ["semver_RANGE"],
semver_range=semver_range,
max_minor=top_python[1],
)
print(f"{max(all_matches)[0]}.{max(all_matches)[1]}")
Expand Down
2 changes: 1 addition & 1 deletion generate_dep_logs/gen-deps-from-repo-python-pkg.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ set -e


# get all extras
VARIANTS_LIST=$(python3 $GITHUB_ACTION_PATH/utils/list_extras.py setup.cfg)
VARIANTS_LIST=$(python3 $GITHUB_ACTION_PATH/utils/list_extras.py .)
VARIANTS_LIST="- $(echo $VARIANTS_LIST)" # "-" signifies regular package
echo $VARIANTS_LIST

Expand Down
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
wipac-dev-tools[semver]
wipac-dev-tools[semver]
toml
49 changes: 36 additions & 13 deletions utils/get_package_name.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
"""Print the package name (metadata section) for a setup.cfg."""

"""Print the package name (metadata section) for a python project."""

import argparse
import configparser
from pathlib import Path

import toml


def get_name(setup_cfg_file: Path) -> str:
def _get_name_pyproject_toml(pyproject_toml: Path) -> str:
"""Get package name."""
with open(pyproject_toml) as f:
toml_dict = toml.load(f)
try:
return toml_dict["project"]["name"]
except KeyError:
return "UNKNOWN"


def _get_name_setup_cfg(setup_cfg_file: Path) -> str:
"""Get package name."""
cfg = configparser.ConfigParser()
cfg.read(setup_cfg_file)
Expand All @@ -16,26 +27,38 @@ def get_name(setup_cfg_file: Path) -> str:
return "UNKNOWN"


def get_name(project_dir: Path) -> str:
"""Get package name."""
if "pyproject.toml" in [f.name for f in project_dir.iterdir()]:
return _get_name_pyproject_toml(project_dir.joinpath("pyproject.toml"))
elif "setup.cfg" in [f.name for f in project_dir.iterdir()]:
return _get_name_setup_cfg(project_dir.joinpath("setup.cfg"))
else:
raise FileNotFoundError(
f"Could not find pyproject.toml or setup.cfg in {project_dir}"
)


if __name__ == "__main__":

def _type_setup_cfg(arg: str) -> Path:
def _type_dir(arg: str) -> Path:
fpath = Path(arg)
if fpath.name != "setup.cfg":
raise ValueError() # excepted by argparse & formatted nicely
if not fpath.exists():
raise FileNotFoundError(arg)
return fpath
raise FileNotFoundError(f"Directory not found: {arg}")
elif not fpath.is_dir():
raise NotADirectoryError(arg)
else:
return fpath

parser = argparse.ArgumentParser(
description="Read 'setup.cfg' and get the [metadata.name] field",
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
)
parser.add_argument(
"setup_cfg_file",
type=_type_setup_cfg,
help="path to the 'setup.cfg' file",
"project_dir",
type=_type_dir,
help="python project dir",
)
args = parser.parse_args()

name = get_name(args.setup_cfg_file)
name = get_name(args.project_dir)
print(name)
50 changes: 35 additions & 15 deletions utils/list_extras.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
"""Print the list of setup/pip extras (options.extras_require section) for a
setup.cfg."""

"""Print the list of setup/pip extras for python project."""

import argparse
import configparser
from pathlib import Path
from typing import Iterator

import toml

def iter_extras(setup_cfg_file: Path) -> Iterator[str]:
"""Yield each extra key."""

def _iter_extras_pyproject_toml(pyproject_toml: Path) -> Iterator[str]:
with open(pyproject_toml) as f:
toml_dict = toml.load(f)
try:
yield from list(toml_dict["project"]["optional-dependencies"].keys())
except KeyError:
return


def _iter_extras_setup_cfg(setup_cfg_file: Path) -> Iterator[str]:
cfg = configparser.ConfigParser()
cfg.read(setup_cfg_file)
try:
Expand All @@ -18,26 +26,38 @@ def iter_extras(setup_cfg_file: Path) -> Iterator[str]:
return


def iter_extras(project_dir: Path) -> Iterator[str]:
"""Yield each extra key."""
if "pyproject.toml" in [f.name for f in project_dir.iterdir()]:
yield from _iter_extras_pyproject_toml(project_dir.joinpath("pyproject.toml"))
elif "setup.cfg" in [f.name for f in project_dir.iterdir()]:
yield from _iter_extras_setup_cfg(project_dir.joinpath("setup.cfg"))
else:
raise FileNotFoundError(
f"Could not find pyproject.toml or setup.cfg in {project_dir}"
)


if __name__ == "__main__":

def _type_setup_cfg(arg: str) -> Path:
def _type_dir(arg: str) -> Path:
fpath = Path(arg)
if fpath.name != "setup.cfg":
raise ValueError() # excepted by argparse & formatted nicely
if not fpath.exists():
raise FileNotFoundError(arg)
return fpath
raise FileNotFoundError(f"Directory not found: {arg}")
elif not fpath.is_dir():
raise NotADirectoryError(arg)
else:
return fpath

parser = argparse.ArgumentParser(
description="Read 'setup.cfg' and get the [options.extras_require] section's keys",
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
)
parser.add_argument(
"setup_cfg_file",
type=_type_setup_cfg,
help="path to the 'setup.cfg' file",
"project_dir",
type=_type_dir,
help="python project dir",
)
args = parser.parse_args()

for extra in iter_extras(args.setup_cfg_file):
for extra in iter_extras(args.project_dir):
print(extra)

0 comments on commit f659152

Please sign in to comment.