-
-
Notifications
You must be signed in to change notification settings - Fork 30.7k
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
gh-113299: Move Argument Clinic CLI into libclinic #115542
Closed
Closed
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
f064435
Reorganise the `Tools/clinic` directory
AlexWaygood 1b423c1
`black Tools/clinic/libclinic/cli.py --line-length 90`
AlexWaygood f2d2c86
Add `__all__`
AlexWaygood 3a1eb0e
update PC\winreg.c
AlexWaygood c5977a5
Fix failing test
AlexWaygood ac08f0f
Import ClinicError directly from libclinic
erlend-aasland 95a59d7
Address review: add Tools/clinic/__main__.py
erlend-aasland 8b7dde7
Add NEWS
erlend-aasland 7720c66
PUll in main
erlend-aasland c5bd50a
Pull in main
erlend-aasland 730c3f9
Revert "Address review: add Tools/clinic/__main__.py"
erlend-aasland 230e321
Pull in main
erlend-aasland File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 3 additions & 0 deletions
3
Misc/NEWS.d/next/Tools-Demos/2024-02-16-00-33-14.gh-issue-113299.lqPMAV.rst
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,3 @@ | ||||||||||||||
The Argument Clinic CLI is now invoked as either :program:`python3 | ||||||||||||||
Tools/clinic` or :program:`python3 Tools/clinic/run_clinic.py`, as | ||||||||||||||
:file:`Tools/clinic/clinic.py` has been refactored into ``libclinic``. | ||||||||||||||
Comment on lines
+1
to
+3
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep, I like this NEWS entry. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,188 @@ | ||
"""Parse arguments passed to the code generator for parsing arguments passed.""" | ||
|
||
import argparse | ||
import inspect | ||
import os | ||
import sys | ||
from typing import NoReturn | ||
|
||
from libclinic import clinic, ClinicError | ||
|
||
__all__ = ["main"] | ||
|
||
|
||
def create_cli() -> argparse.ArgumentParser: | ||
cmdline = argparse.ArgumentParser( | ||
description="""Preprocessor for CPython C files. | ||
|
||
The purpose of the Argument Clinic is automating all the boilerplate involved | ||
with writing argument parsing code for builtins and providing introspection | ||
signatures ("docstrings") for CPython builtins. | ||
|
||
For more information see https://devguide.python.org/development-tools/clinic/""", | ||
) | ||
cmdline.add_argument( | ||
"-f", "--force", action="store_true", help="force output regeneration" | ||
) | ||
cmdline.add_argument( | ||
"-o", "--output", type=str, help="redirect file output to OUTPUT" | ||
) | ||
cmdline.add_argument( | ||
"-v", "--verbose", action="store_true", help="enable verbose mode" | ||
) | ||
cmdline.add_argument( | ||
"--converters", | ||
action="store_true", | ||
help=("print a list of all supported converters " "and return converters"), | ||
) | ||
cmdline.add_argument( | ||
"--make", | ||
action="store_true", | ||
help="walk --srcdir to run over all relevant files", | ||
) | ||
cmdline.add_argument( | ||
"--srcdir", | ||
type=str, | ||
default=os.curdir, | ||
help="the directory tree to walk in --make mode", | ||
) | ||
cmdline.add_argument( | ||
"--exclude", | ||
type=str, | ||
action="append", | ||
help=("a file to exclude in --make mode; " "can be given multiple times"), | ||
) | ||
cmdline.add_argument( | ||
"--limited", | ||
dest="limited_capi", | ||
action="store_true", | ||
help="use the Limited C API", | ||
) | ||
cmdline.add_argument( | ||
"filename", | ||
metavar="FILE", | ||
type=str, | ||
nargs="*", | ||
help="the list of files to process", | ||
) | ||
return cmdline | ||
|
||
|
||
def run_clinic(parser: argparse.ArgumentParser, ns: argparse.Namespace) -> None: | ||
if ns.converters: | ||
if ns.filename: | ||
parser.error("can't specify --converters and a filename at the same time") | ||
converters: list[tuple[str, str]] = [] | ||
return_converters: list[tuple[str, str]] = [] | ||
ignored = set( | ||
""" | ||
add_c_converter | ||
add_c_return_converter | ||
add_default_legacy_c_converter | ||
add_legacy_c_converter | ||
""".strip().split() | ||
) | ||
|
||
module = vars(clinic) | ||
for name in module: | ||
for suffix, ids in ( | ||
("_return_converter", return_converters), | ||
("_converter", converters), | ||
): | ||
if name in ignored: | ||
continue | ||
if name.endswith(suffix): | ||
ids.append((name, name.removesuffix(suffix))) | ||
break | ||
print() | ||
|
||
print("Legacy converters:") | ||
legacy = sorted(clinic.legacy_converters) | ||
print(" " + " ".join(c for c in legacy if c[0].isupper())) | ||
print(" " + " ".join(c for c in legacy if c[0].islower())) | ||
print() | ||
|
||
for title, attribute, ids in ( | ||
("Converters", "converter_init", converters), | ||
("Return converters", "return_converter_init", return_converters), | ||
): | ||
print(title + ":") | ||
longest = -1 | ||
for name, short_name in ids: | ||
longest = max(longest, len(short_name)) | ||
for name, short_name in sorted(ids, key=lambda x: x[1].lower()): | ||
cls = module[name] | ||
callable = getattr(cls, attribute, None) | ||
if not callable: | ||
continue | ||
signature = inspect.signature(callable) | ||
parameters = [] | ||
for parameter_name, parameter in signature.parameters.items(): | ||
if parameter.kind == inspect.Parameter.KEYWORD_ONLY: | ||
if parameter.default != inspect.Parameter.empty: | ||
s = f"{parameter_name}={parameter.default!r}" | ||
else: | ||
s = parameter_name | ||
parameters.append(s) | ||
print(" {}({})".format(short_name, ", ".join(parameters))) | ||
print() | ||
print( | ||
"All converters also accept (c_default=None, py_default=None, annotation=None)." | ||
) | ||
print("All return converters also accept (py_default=None).") | ||
return | ||
|
||
if ns.make: | ||
if ns.output or ns.filename: | ||
parser.error("can't use -o or filenames with --make") | ||
if not ns.srcdir: | ||
parser.error("--srcdir must not be empty with --make") | ||
if ns.exclude: | ||
excludes = [os.path.join(ns.srcdir, f) for f in ns.exclude] | ||
excludes = [os.path.normpath(f) for f in excludes] | ||
else: | ||
excludes = [] | ||
for root, dirs, files in os.walk(ns.srcdir): | ||
for rcs_dir in (".svn", ".git", ".hg", "build", "externals"): | ||
if rcs_dir in dirs: | ||
dirs.remove(rcs_dir) | ||
for filename in files: | ||
# handle .c, .cpp and .h files | ||
if not filename.endswith((".c", ".cpp", ".h")): | ||
continue | ||
path = os.path.join(root, filename) | ||
path = os.path.normpath(path) | ||
if path in excludes: | ||
continue | ||
if ns.verbose: | ||
print(path) | ||
clinic.parse_file(path, verify=not ns.force, limited_capi=ns.limited_capi) | ||
return | ||
|
||
if not ns.filename: | ||
parser.error("no input files") | ||
|
||
if ns.output and len(ns.filename) > 1: | ||
parser.error("can't use -o with multiple filenames") | ||
|
||
for filename in ns.filename: | ||
if ns.verbose: | ||
print(filename) | ||
clinic.parse_file( | ||
filename, | ||
output=ns.output, | ||
verify=not ns.force, | ||
limited_capi=ns.limited_capi, | ||
) | ||
|
||
|
||
def main(argv: list[str] | None = None) -> NoReturn: | ||
parser = create_cli() | ||
args = parser.parse_args(argv) | ||
try: | ||
run_clinic(parser, args) | ||
except ClinicError as exc: | ||
sys.stderr.write(exc.report()) | ||
sys.exit(1) | ||
else: | ||
sys.exit(0) |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The NEWS entry is outdated, there is no
__main__.py
script.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ohh, thanks; the NEWS entry was not part of the commit I reverted. Good catch.