Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add optional dependencies section #18

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ venv.bak/
# Rope project settings
.ropeproject

# JetBrains IDEs project settings
.idea

# mkdocs documentation
/site

Expand Down
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,19 @@ pr_summary_regex = "^```release-note\\s*(?P<summary>[\\s\\S]*?\\w[\\s\\S]*?)\\s*
# group named "label".
pr_summary_label_regex = """{[^}]*?label=[\\"](?P<label>[^\\"]+)[^}]*?}"""

# Show the required Python version if `project.requires-python` is present
# in the pyproject.toml at the last given revision.
show_required_python = true

# Show the required dependencies if `project.dependencies` is present
# in the pyproject.toml at the last given revision.
show_required_dependencies = true

# Show the given optional dependencies if `project.optional-dependencies` is
# present in the pyproject.toml at the last given revision.
# E.g. ["test"]
show_optional_dependencies = []

# If any of a pull request's labels matches one of the regexes on the left side
# its summary will appear in the appropriate section with the title given on
# the right side. If a pull request doesn't match one of these categories it is
Expand Down
35 changes: 34 additions & 1 deletion src/changelist/_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@
from ._config import add_config_defaults, local_config, remote_config
from ._format import MdFormatter, RstFormatter
from ._objects import ChangeNote, Contributor
from ._query import commits_between, contributors, pull_requests_from_commits
from ._query import (
commits_between,
contributors,
pull_requests_from_commits,
pyproject_dependencies,
)

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -152,6 +157,31 @@ def main(
pull_requests=lazy_tqdm(pull_requests, desc="Fetching reviewers"),
)

python_dep = None
required_deps = []
optional_deps = {}
if config.keys() & {
"show_required_python",
"show_required_dependencies",
"show_optional_dependencies",
}:
print("Fetching dependencies...", file=sys.stderr)
python_dep, required_deps, optional_deps = pyproject_dependencies(
gh, org_repo, stop_rev
)
if not config["show_required_python"]:
python_dep = None
if not config["show_required_dependencies"]:
required_deps = []
if config["show_optional_dependencies"]:
optional_deps = {
key: value
for key, value in optional_deps.items()
if key in config["show_optional_dependencies"]
}
else:
optional_deps = {}

print("Formatting notes...", file=sys.stderr)
change_notes = ChangeNote.from_pull_requests(
pull_requests,
Expand All @@ -165,6 +195,9 @@ def main(
change_notes=change_notes,
authors=Contributor.from_named_users(authors),
reviewers=Contributor.from_named_users(reviewers),
required_python=python_dep,
required_dependencies=required_deps,
optional_dependencies=optional_deps,
version=version,
title_template=config["title_template"],
intro_template=config["intro_template"],
Expand Down
41 changes: 41 additions & 0 deletions src/changelist/_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ class MdFormatter:
change_notes: set[ChangeNote]
authors: set[Contributor]
reviewers: set[Contributor]
required_python: str
required_dependencies: Iterable[str]
optional_dependencies: dict[str, Iterable[str]]

version: str
title_template: str
Expand Down Expand Up @@ -51,6 +54,11 @@ def iter_lines(self) -> Iterable[str]:
yield from self._format_intro()
for title, notes in self._notes_by_section.items():
yield from self._format_change_section(title, notes)
yield from self._format_dependencies_section(
required_python=self.required_python,
required_dependencies=self.required_dependencies,
optional_dependencies=self.optional_dependencies,
)
yield from self._format_contributor_section(self.authors, self.reviewers)
yield from self._format_outro()

Expand Down Expand Up @@ -146,6 +154,39 @@ def _format_contributor_section(
yield from sorted(reviewers_lines, key=lambda s: s.lower())
yield "\n"

def _format_dependencies_section(
self, required_python, required_dependencies, optional_dependencies
):
if required_python or required_dependencies or optional_dependencies:
yield from self._format_section_title("Dependencies", level=2)
yield "\n"

if required_python:
yield f"Python `{required_python}` is required.\n"
yield "\n"

if required_dependencies:
yield "Required dependencies:\n"
yield "\n"
for dep in sorted(required_dependencies, key=lambda x: x.lower()):
line = f"`{dep}`"
line = self._sanitize_text(line)
yield f"- {line}\n"
yield "\n"

if optional_dependencies:
yield "Optional dependencies:\n"
yield "\n"
for name, deps in optional_dependencies.items():
line = f"`{name}`"
line = self._sanitize_text(line)
yield f"- {line}\n"
for dep in sorted(deps, key=lambda x: x.lower()):
line = f"`{dep}`"
line = self._sanitize_text(line)
yield f" - {line}\n"
yield "\n"

def _format_intro(self):
intro = self.intro_template.format(
repo_name=self.repo_name, version=self.version
Expand Down
30 changes: 29 additions & 1 deletion src/changelist/_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@
from collections.abc import Iterable
from dataclasses import dataclass

try:
import tomllib
except ModuleNotFoundError:
import tomli as tomllib

import requests
from github import Github
from github import Github, UnknownObjectException
from github.Commit import Commit
from github.NamedUser import NamedUser
from github.PullRequest import PullRequest
Expand Down Expand Up @@ -174,3 +179,26 @@ def contributors(
reviewers.add(review.user)

return authors, reviewers


def pyproject_dependencies(
gh: Github,
org_repo: str,
rev: str,
) -> tuple[str | None, list[str], dict[str, list[str]]]:
"""Fetch dependencies from pyproject.toml at the given revision."""
repo = gh.get_repo(org_repo)
try:
file = repo.get_contents("pyproject.toml", ref=rev)
logger.debug("found pyproject.toml in %s@%s", org_repo, rev)
content = file.decoded_content.decode()
except UnknownObjectException:
content = ""
pyproject = tomllib.loads(content)
pyproject = pyproject.get("project", {})

python_dep = pyproject.get("requires-python")
runtime_deps = pyproject.get("dependencies", [])
extra_deps = pyproject.get("optional-dependencies", {})

return python_dep, runtime_deps, extra_deps
13 changes: 13 additions & 0 deletions src/changelist/default_config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,19 @@ pr_summary_regex = "^```release-note\\s*(?P<summary>[\\s\\S]*?\\w[\\s\\S]*?)\\s*
# group named "label".
pr_summary_label_regex = """{[^}]*?label=[\\"](?P<label>[^\\"]+)[^}]*?}"""

# Show the required Python version if `project.requires-python` is present
# in the pyproject.toml at the last given revision.
show_required_python = true

# Show the required dependencies if `project.dependencies` is present
# in the pyproject.toml at the last given revision.
show_required_dependencies = true

# Show the given optional dependencies if `project.optional-dependencies` is
# present in the pyproject.toml at the last given revision.
# E.g. ["test"]
show_optional_dependencies = []

# If any of a pull request's labels matches one of the regexes on the left side
# its summary will appear in the appropriate section with the title given on
# the right side. If a pull request doesn't match one of these categories it is
Expand Down
Loading